django-cfg 1.3.1__py3-none-any.whl → 1.3.5__py3-none-any.whl
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.
- django_cfg/__init__.py +1 -1
- django_cfg/apps/payments/admin_interface/old/payments/base.html +175 -0
- django_cfg/apps/payments/admin_interface/old/payments/components/dev_tool_card.html +125 -0
- django_cfg/apps/payments/admin_interface/old/payments/components/ngrok_status_card.html +113 -0
- django_cfg/apps/payments/admin_interface/old/payments/components/status_card.html +35 -0
- django_cfg/apps/payments/admin_interface/old/payments/payment_dashboard.html +309 -0
- django_cfg/apps/payments/admin_interface/old/payments/payment_form.html +303 -0
- django_cfg/apps/payments/admin_interface/old/payments/payment_list.html +382 -0
- django_cfg/apps/payments/admin_interface/old/payments/webhook_dashboard.html +518 -0
- django_cfg/apps/payments/{static → admin_interface/old/static}/payments/css/components.css +248 -9
- django_cfg/apps/payments/admin_interface/old/static/payments/js/ngrok-status.js +163 -0
- django_cfg/apps/payments/admin_interface/serializers/__init__.py +39 -0
- django_cfg/apps/payments/admin_interface/serializers/payment_serializers.py +149 -0
- django_cfg/apps/payments/admin_interface/serializers/webhook_serializers.py +114 -0
- django_cfg/apps/payments/admin_interface/templates/payments/base.html +55 -90
- django_cfg/apps/payments/admin_interface/templates/payments/components/dialog.html +81 -0
- django_cfg/apps/payments/admin_interface/templates/payments/components/ngrok_help_dialog.html +112 -0
- django_cfg/apps/payments/admin_interface/templates/payments/components/ngrok_status.html +175 -0
- django_cfg/apps/payments/admin_interface/templates/payments/components/status_card.html +21 -17
- django_cfg/apps/payments/admin_interface/templates/payments/payment_dashboard.html +123 -250
- django_cfg/apps/payments/admin_interface/templates/payments/payment_form.html +170 -269
- django_cfg/apps/payments/admin_interface/templates/payments/payment_list.html +152 -355
- django_cfg/apps/payments/admin_interface/templates/payments/webhook_dashboard.html +202 -551
- django_cfg/apps/payments/admin_interface/views/__init__.py +25 -14
- django_cfg/apps/payments/admin_interface/views/api/__init__.py +20 -0
- django_cfg/apps/payments/admin_interface/views/api/payments.py +191 -0
- django_cfg/apps/payments/admin_interface/views/api/stats.py +206 -0
- django_cfg/apps/payments/admin_interface/views/api/users.py +60 -0
- django_cfg/apps/payments/admin_interface/views/api/webhook_admin.py +257 -0
- django_cfg/apps/payments/admin_interface/views/api/webhook_public.py +70 -0
- django_cfg/apps/payments/admin_interface/views/base.py +114 -0
- django_cfg/apps/payments/admin_interface/views/dashboard.py +60 -0
- django_cfg/apps/payments/admin_interface/views/forms.py +94 -0
- django_cfg/apps/payments/config/helpers.py +2 -2
- django_cfg/apps/payments/management/commands/cleanup_expired_data.py +429 -0
- django_cfg/apps/payments/management/commands/currency_stats.py +443 -0
- django_cfg/apps/payments/management/commands/manage_currencies.py +9 -20
- django_cfg/apps/payments/management/commands/manage_providers.py +5 -5
- django_cfg/apps/payments/management/commands/process_pending_payments.py +357 -0
- django_cfg/apps/payments/management/commands/test_providers.py +434 -0
- django_cfg/apps/payments/middleware/api_access.py +35 -34
- django_cfg/apps/payments/migrations/0001_initial.py +1 -1
- django_cfg/apps/payments/models/balance.py +5 -2
- django_cfg/apps/payments/models/managers/api_key_managers.py +6 -2
- django_cfg/apps/payments/models/managers/balance_managers.py +3 -3
- django_cfg/apps/payments/models/managers/payment_managers.py +5 -0
- django_cfg/apps/payments/models/managers/subscription_managers.py +3 -3
- django_cfg/apps/payments/models/subscriptions.py +0 -24
- django_cfg/apps/payments/services/cache/__init__.py +1 -1
- django_cfg/apps/payments/services/cache_service/__init__.py +143 -0
- django_cfg/apps/payments/services/cache_service/api_key_cache.py +37 -0
- django_cfg/apps/payments/services/cache_service/interfaces.py +32 -0
- django_cfg/apps/payments/services/cache_service/keys.py +49 -0
- django_cfg/apps/payments/services/cache_service/rate_limit_cache.py +47 -0
- django_cfg/apps/payments/services/cache_service/simple_cache.py +101 -0
- django_cfg/apps/payments/services/core/balance_service.py +13 -2
- django_cfg/apps/payments/services/core/payment_service.py +49 -22
- django_cfg/apps/payments/services/integrations/ngrok_service.py +3 -3
- django_cfg/apps/payments/services/providers/registry.py +20 -0
- django_cfg/apps/payments/signals/api_key_signals.py +2 -2
- django_cfg/apps/payments/signals/balance_signals.py +8 -5
- django_cfg/apps/payments/static/payments/js/api-client.js +385 -0
- django_cfg/apps/payments/static/payments/js/ngrok-status.js +58 -0
- django_cfg/apps/payments/static/payments/js/payment-dashboard.js +50 -0
- django_cfg/apps/payments/static/payments/js/payment-form.js +175 -0
- django_cfg/apps/payments/static/payments/js/payment-list.js +95 -0
- django_cfg/apps/payments/static/payments/js/webhook-dashboard.js +154 -0
- django_cfg/apps/payments/urls.py +4 -0
- django_cfg/apps/payments/urls_admin.py +37 -18
- django_cfg/apps/payments/views/api/api_keys.py +14 -0
- django_cfg/apps/payments/views/api/base.py +1 -0
- django_cfg/apps/payments/views/api/currencies.py +2 -2
- django_cfg/apps/payments/views/api/payments.py +11 -5
- django_cfg/apps/payments/views/api/subscriptions.py +36 -31
- django_cfg/apps/payments/views/overview/__init__.py +40 -0
- django_cfg/apps/payments/views/overview/serializers.py +205 -0
- django_cfg/apps/payments/views/overview/services.py +439 -0
- django_cfg/apps/payments/views/overview/urls.py +27 -0
- django_cfg/apps/payments/views/overview/views.py +231 -0
- django_cfg/apps/payments/views/serializers/api_keys.py +20 -6
- django_cfg/apps/payments/views/serializers/balances.py +5 -8
- django_cfg/apps/payments/views/serializers/currencies.py +2 -6
- django_cfg/apps/payments/views/serializers/payments.py +37 -32
- django_cfg/apps/payments/views/serializers/subscriptions.py +4 -26
- django_cfg/apps/urls.py +2 -1
- django_cfg/core/config.py +25 -15
- django_cfg/core/generation.py +12 -12
- django_cfg/core/integration/display/startup.py +1 -1
- django_cfg/core/validation.py +4 -4
- django_cfg/management/commands/show_config.py +2 -2
- django_cfg/management/commands/tree.py +1 -3
- django_cfg/middleware/__init__.py +2 -0
- django_cfg/middleware/static_nocache.py +55 -0
- django_cfg/models/payments.py +13 -15
- django_cfg/models/security.py +15 -0
- django_cfg/modules/django_ngrok.py +6 -0
- django_cfg/modules/django_unfold/dashboard.py +1 -3
- django_cfg/utils/smart_defaults.py +51 -5
- {django_cfg-1.3.1.dist-info → django_cfg-1.3.5.dist-info}/METADATA +1 -1
- {django_cfg-1.3.1.dist-info → django_cfg-1.3.5.dist-info}/RECORD +111 -69
- django_cfg/apps/payments/admin_interface/templates/payments/components/dev_tool_card.html +0 -38
- django_cfg/apps/payments/admin_interface/views/payment_views.py +0 -259
- django_cfg/apps/payments/admin_interface/views/webhook_dashboard.py +0 -37
- django_cfg/apps/payments/services/cache/cache_service.py +0 -235
- /django_cfg/apps/payments/admin_interface/{templates → old}/payments/components/loading_spinner.html +0 -0
- /django_cfg/apps/payments/admin_interface/{templates → old}/payments/components/notification.html +0 -0
- /django_cfg/apps/payments/admin_interface/{templates → old}/payments/components/provider_card.html +0 -0
- /django_cfg/apps/payments/admin_interface/{templates → old}/payments/currency_converter.html +0 -0
- /django_cfg/apps/payments/admin_interface/{templates → old}/payments/payment_status.html +0 -0
- /django_cfg/apps/payments/{static → admin_interface/old/static}/payments/css/dashboard.css +0 -0
- /django_cfg/apps/payments/{static → admin_interface/old/static}/payments/js/components.js +0 -0
- /django_cfg/apps/payments/{static → admin_interface/old/static}/payments/js/utils.js +0 -0
- {django_cfg-1.3.1.dist-info → django_cfg-1.3.5.dist-info}/WHEEL +0 -0
- {django_cfg-1.3.1.dist-info → django_cfg-1.3.5.dist-info}/entry_points.txt +0 -0
- {django_cfg-1.3.1.dist-info → django_cfg-1.3.5.dist-info}/licenses/LICENSE +0 -0
@@ -1,382 +1,179 @@
|
|
1
1
|
{% extends 'payments/base.html' %}
|
2
2
|
{% load static %}
|
3
|
-
{% load payment_tags %}
|
4
3
|
|
5
|
-
{% block
|
6
|
-
|
4
|
+
{% block title %}Payments - Payment Admin{% endblock %}
|
5
|
+
|
6
|
+
{% block page_title %}Payments{% endblock %}
|
7
|
+
{% block page_subtitle %}Manage and monitor payment transactions{% endblock %}
|
7
8
|
|
8
9
|
{% block content %}
|
9
10
|
<div x-data="paymentList()" x-init="init()">
|
10
|
-
<!--
|
11
|
-
<div class="
|
12
|
-
<div class="
|
13
|
-
<
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
11
|
+
<!-- Actions Bar -->
|
12
|
+
<div class="mb-6 flex flex-col sm:flex-row sm:items-center sm:justify-between">
|
13
|
+
<div class="flex items-center space-x-4">
|
14
|
+
<a href="{% url 'cfg_payments_admin:payment-form' %}"
|
15
|
+
class="inline-flex items-center px-4 py-2 bg-blue-600 text-white text-sm font-medium rounded-md hover:bg-blue-700">
|
16
|
+
<span class="material-icons-outlined mr-2">add</span>
|
17
|
+
Create Payment
|
18
|
+
</a>
|
19
|
+
<button @click="refreshPayments()"
|
20
|
+
class="inline-flex items-center px-4 py-2 bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-600 text-gray-700 dark:text-gray-300 text-sm font-medium rounded-md hover:bg-gray-50 dark:hover:bg-gray-700">
|
21
|
+
<span class="material-icons-outlined mr-2" :class="{ 'animate-spin': loading }">refresh</span>
|
22
|
+
Refresh
|
20
23
|
</button>
|
21
24
|
</div>
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
<!-- Status Filter -->
|
35
|
-
<div>
|
36
|
-
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">Status</label>
|
37
|
-
<select x-model="filters.status" @change="applyFilters()"
|
38
|
-
class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md bg-white dark:bg-gray-700 text-gray-900 dark:text-white">
|
39
|
-
<option value="">All Statuses</option>
|
40
|
-
<option value="pending">Pending</option>
|
41
|
-
<option value="processing">Processing</option>
|
42
|
-
<option value="completed">Completed</option>
|
43
|
-
<option value="failed">Failed</option>
|
44
|
-
<option value="cancelled">Cancelled</option>
|
45
|
-
</select>
|
46
|
-
</div>
|
47
|
-
|
48
|
-
<!-- Provider Filter -->
|
49
|
-
<div>
|
50
|
-
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">Provider</label>
|
51
|
-
<select x-model="filters.provider" @change="applyFilters()"
|
52
|
-
class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md bg-white dark:bg-gray-700 text-gray-900 dark:text-white">
|
53
|
-
<option value="">All Providers</option>
|
54
|
-
<option value="nowpayments">NowPayments</option>
|
55
|
-
<option value="stripe">Stripe</option>
|
56
|
-
<option value="cryptapi">CryptAPI</option>
|
57
|
-
</select>
|
58
|
-
</div>
|
59
|
-
|
60
|
-
<!-- Date Range -->
|
61
|
-
<div>
|
62
|
-
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">Date Range</label>
|
63
|
-
<select x-model="filters.dateRange" @change="applyFilters()"
|
64
|
-
class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md bg-white dark:bg-gray-700 text-gray-900 dark:text-white">
|
65
|
-
<option value="">All Time</option>
|
66
|
-
<option value="today">Today</option>
|
67
|
-
<option value="week">This Week</option>
|
68
|
-
<option value="month">This Month</option>
|
69
|
-
<option value="quarter">This Quarter</option>
|
70
|
-
</select>
|
25
|
+
|
26
|
+
<!-- Search and Filters -->
|
27
|
+
<div class="mt-4 sm:mt-0 flex items-center space-x-4">
|
28
|
+
<div class="relative">
|
29
|
+
<input type="text"
|
30
|
+
x-model="filters.search"
|
31
|
+
@input.debounce.300ms="applyFilters()"
|
32
|
+
placeholder="Search payments..."
|
33
|
+
class="block w-full pl-10 pr-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md text-sm bg-white dark:bg-gray-700 text-gray-900 dark:text-white">
|
34
|
+
<div class="absolute inset-y-0 left-0 pl-3 flex items-center">
|
35
|
+
<span class="material-icons-outlined text-gray-400 text-sm">search</span>
|
71
36
|
</div>
|
72
37
|
</div>
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
<button @click="exportPayments()"
|
84
|
-
class="btn btn-outline text-sm">
|
85
|
-
<span class="material-icons-outlined mr-1 text-sm">download</span>
|
86
|
-
Export
|
87
|
-
</button>
|
88
|
-
<a href="{% url 'cfg_payments_admin:payment-create' %}"
|
89
|
-
class="btn btn-primary text-sm">
|
90
|
-
<span class="material-icons-outlined mr-1 text-sm">add</span>
|
91
|
-
New Payment
|
92
|
-
</a>
|
38
|
+
|
39
|
+
<select x-model="filters.status"
|
40
|
+
@change="applyFilters()"
|
41
|
+
class="block px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md text-sm bg-white dark:bg-gray-700 text-gray-900 dark:text-white">
|
42
|
+
<option value="">All Status</option>
|
43
|
+
<option value="pending">Pending</option>
|
44
|
+
<option value="completed">Completed</option>
|
45
|
+
<option value="failed">Failed</option>
|
46
|
+
<option value="cancelled">Cancelled</option>
|
47
|
+
</select>
|
93
48
|
</div>
|
94
49
|
</div>
|
95
50
|
|
96
51
|
<!-- Payments Table -->
|
97
|
-
<div class="
|
98
|
-
<div class="
|
99
|
-
<
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
<
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
:class="{
|
137
|
-
'text-green-600 dark:text-green-400': payment.status === 'completed',
|
138
|
-
'text-yellow-600 dark:text-yellow-400': payment.status === 'pending',
|
139
|
-
'text-blue-600 dark:text-blue-400': payment.status === 'processing',
|
140
|
-
'text-red-600 dark:text-red-400': ['failed', 'cancelled'].includes(payment.status)
|
141
|
-
}"
|
142
|
-
x-text="getStatusIcon(payment.status)">
|
143
|
-
</span>
|
144
|
-
</div>
|
145
|
-
<div>
|
146
|
-
<div class="text-sm font-medium text-gray-900 dark:text-white" x-text="payment.external_id || payment.id.substring(0, 8)"></div>
|
147
|
-
<div class="text-sm text-gray-500 dark:text-gray-400" x-text="payment.currency_code"></div>
|
148
|
-
</div>
|
52
|
+
<div class="bg-white dark:bg-gray-800 shadow rounded-lg overflow-hidden">
|
53
|
+
<div class="px-6 py-4 border-b border-gray-200 dark:border-gray-700">
|
54
|
+
<h3 class="text-lg font-medium text-gray-900 dark:text-white">
|
55
|
+
Recent Payments
|
56
|
+
<span class="ml-2 text-sm font-normal text-gray-500 dark:text-gray-400" x-text="`(${filteredPayments.length})`"></span>
|
57
|
+
</h3>
|
58
|
+
</div>
|
59
|
+
|
60
|
+
<div class="overflow-x-auto">
|
61
|
+
<table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
|
62
|
+
<thead class="bg-gray-50 dark:bg-gray-700">
|
63
|
+
<tr>
|
64
|
+
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">
|
65
|
+
Payment
|
66
|
+
</th>
|
67
|
+
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">
|
68
|
+
Amount
|
69
|
+
</th>
|
70
|
+
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">
|
71
|
+
Status
|
72
|
+
</th>
|
73
|
+
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">
|
74
|
+
Provider
|
75
|
+
</th>
|
76
|
+
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">
|
77
|
+
Created
|
78
|
+
</th>
|
79
|
+
<th class="px-6 py-3 text-right text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">
|
80
|
+
Actions
|
81
|
+
</th>
|
82
|
+
</tr>
|
83
|
+
</thead>
|
84
|
+
<tbody class="bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700">
|
85
|
+
<template x-for="payment in paginatedPayments" :key="payment.id">
|
86
|
+
<tr class="hover:bg-gray-50 dark:hover:bg-gray-700">
|
87
|
+
<td class="px-6 py-4 whitespace-nowrap">
|
88
|
+
<div class="flex items-center">
|
89
|
+
<div class="w-10 h-10 bg-blue-100 dark:bg-blue-900 rounded-full flex items-center justify-center mr-3">
|
90
|
+
<span class="material-icons-outlined text-blue-600 dark:text-blue-400">payment</span>
|
149
91
|
</div>
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
<div class="text-sm text-gray-500 dark:text-gray-400" x-show="payment.amount_crypto" x-text="payment.amount_crypto + ' ' + payment.currency_code"></div>
|
154
|
-
</td>
|
155
|
-
<td class="px-6 py-4 whitespace-nowrap">
|
156
|
-
<span class="inline-flex px-2 py-1 text-xs font-semibold rounded-full"
|
157
|
-
:class="{
|
158
|
-
'bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200': payment.status === 'completed',
|
159
|
-
'bg-yellow-100 text-yellow-800 dark:bg-yellow-900 dark:text-yellow-200': payment.status === 'pending',
|
160
|
-
'bg-blue-100 text-blue-800 dark:bg-blue-900 dark:text-blue-200': payment.status === 'processing',
|
161
|
-
'bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-200': ['failed', 'cancelled'].includes(payment.status)
|
162
|
-
}"
|
163
|
-
x-text="payment.status.charAt(0).toUpperCase() + payment.status.slice(1)">
|
164
|
-
</span>
|
165
|
-
</td>
|
166
|
-
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900 dark:text-white" x-text="payment.provider.charAt(0).toUpperCase() + payment.provider.slice(1)"></td>
|
167
|
-
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500 dark:text-gray-400" x-text="formatDate(payment.created_at)"></td>
|
168
|
-
<td class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
|
169
|
-
<div class="flex items-center justify-end space-x-2">
|
170
|
-
<a :href="`{% url 'cfg_payments_admin:payment-detail' '00000000-0000-0000-0000-000000000000' %}`.replace('00000000-0000-0000-0000-000000000000', payment.id)"
|
171
|
-
class="text-blue-600 dark:text-blue-400 hover:text-blue-800 dark:hover:text-blue-300">
|
172
|
-
<span class="material-icons-outlined text-sm">visibility</span>
|
173
|
-
</a>
|
174
|
-
<button @click="copyPaymentId(payment.id)"
|
175
|
-
class="text-gray-400 hover:text-gray-600 dark:hover:text-gray-200">
|
176
|
-
<span class="material-icons-outlined text-sm">content_copy</span>
|
177
|
-
</button>
|
92
|
+
<div>
|
93
|
+
<div class="text-sm font-medium text-gray-900 dark:text-white" x-text="payment.id.substring(0, 8)"></div>
|
94
|
+
<div class="text-sm text-gray-500 dark:text-gray-400" x-text="payment.external_id || 'No external ID'"></div>
|
178
95
|
</div>
|
179
|
-
</
|
180
|
-
</
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
96
|
+
</div>
|
97
|
+
</td>
|
98
|
+
<td class="px-6 py-4 whitespace-nowrap">
|
99
|
+
<div class="text-sm font-medium text-gray-900 dark:text-white" x-text="`$${payment.amount_usd}`"></div>
|
100
|
+
<div class="text-sm text-gray-500 dark:text-gray-400" x-text="payment.currency_code"></div>
|
101
|
+
</td>
|
102
|
+
<td class="px-6 py-4 whitespace-nowrap">
|
103
|
+
<span class="inline-flex px-2 py-1 text-xs font-semibold rounded-full"
|
104
|
+
:class="{
|
105
|
+
'bg-green-100 text-green-800 dark:bg-green-900/20 dark:text-green-400': payment.status === 'completed',
|
106
|
+
'bg-yellow-100 text-yellow-800 dark:bg-yellow-900/20 dark:text-yellow-400': payment.status === 'pending',
|
107
|
+
'bg-red-100 text-red-800 dark:bg-red-900/20 dark:text-red-400': payment.status === 'failed',
|
108
|
+
'bg-gray-100 text-gray-800 dark:bg-gray-900/20 dark:text-gray-400': payment.status === 'cancelled'
|
109
|
+
}"
|
110
|
+
x-text="payment.status">
|
111
|
+
</span>
|
112
|
+
</td>
|
113
|
+
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900 dark:text-white" x-text="payment.provider"></td>
|
114
|
+
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500 dark:text-gray-400" x-text="formatDate(payment.created_at)"></td>
|
115
|
+
<td class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
|
116
|
+
<div class="flex items-center justify-end space-x-2">
|
117
|
+
<a :href="`/cfg/admin/django_cfg_payments/admin/payments/${payment.id}/`"
|
118
|
+
class="text-blue-600 hover:text-blue-900 dark:text-blue-400 dark:hover:text-blue-300">
|
119
|
+
<span class="material-icons-outlined text-sm">visibility</span>
|
120
|
+
</a>
|
121
|
+
<button @click="refreshPayment(payment.id)"
|
122
|
+
class="text-gray-400 hover:text-gray-600 dark:hover:text-gray-200">
|
123
|
+
<span class="material-icons-outlined text-sm">refresh</span>
|
124
|
+
</button>
|
125
|
+
</div>
|
126
|
+
</td>
|
127
|
+
</tr>
|
128
|
+
</template>
|
129
|
+
</tbody>
|
130
|
+
</table>
|
201
131
|
</div>
|
202
|
-
</div>
|
203
132
|
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
<span class="material-icons-outlined text-sm">chevron_left</span>
|
215
|
-
Previous
|
216
|
-
</button>
|
217
|
-
<button @click="goToPage(currentPage + 1)"
|
218
|
-
:disabled="currentPage >= totalPages"
|
219
|
-
class="btn btn-outline text-sm"
|
220
|
-
:class="{ 'opacity-50 cursor-not-allowed': currentPage >= totalPages }">
|
221
|
-
Next
|
222
|
-
<span class="material-icons-outlined text-sm">chevron_right</span>
|
223
|
-
</button>
|
133
|
+
<!-- Empty State -->
|
134
|
+
<div x-show="filteredPayments.length === 0 && !loading" class="text-center py-12">
|
135
|
+
<span class="material-icons-outlined text-gray-400 text-6xl mb-4">payment</span>
|
136
|
+
<h3 class="text-lg font-medium text-gray-900 dark:text-white mb-2">No payments found</h3>
|
137
|
+
<p class="text-gray-500 dark:text-gray-400 mb-4">Get started by creating your first payment.</p>
|
138
|
+
<a href="{% url 'cfg_payments_admin:payment-form' %}"
|
139
|
+
class="inline-flex items-center px-4 py-2 bg-blue-600 text-white text-sm font-medium rounded-md hover:bg-blue-700">
|
140
|
+
<span class="material-icons-outlined mr-2">add</span>
|
141
|
+
Create Payment
|
142
|
+
</a>
|
224
143
|
</div>
|
225
|
-
</div>
|
226
144
|
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
145
|
+
<!-- Loading State -->
|
146
|
+
<div x-show="loading" class="text-center py-12">
|
147
|
+
<div class="inline-block animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600"></div>
|
148
|
+
<p class="mt-2 text-sm text-gray-500 dark:text-gray-400">Loading payments...</p>
|
149
|
+
</div>
|
231
150
|
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
151
|
+
<!-- Pagination -->
|
152
|
+
<div x-show="filteredPayments.length > pageSize" class="px-6 py-4 border-t border-gray-200 dark:border-gray-700">
|
153
|
+
<div class="flex items-center justify-between">
|
154
|
+
<div class="text-sm text-gray-700 dark:text-gray-300">
|
155
|
+
Showing <span x-text="((currentPage - 1) * pageSize) + 1"></span> to
|
156
|
+
<span x-text="Math.min(currentPage * pageSize, filteredPayments.length)"></span> of
|
157
|
+
<span x-text="filteredPayments.length"></span> results
|
158
|
+
</div>
|
159
|
+
<div class="flex space-x-2">
|
160
|
+
<button @click="currentPage--"
|
161
|
+
:disabled="currentPage === 1"
|
162
|
+
class="px-3 py-1 text-sm bg-white dark:bg-gray-700 border border-gray-300 dark:border-gray-600 rounded-md disabled:opacity-50">
|
163
|
+
Previous
|
164
|
+
</button>
|
165
|
+
<button @click="currentPage++"
|
166
|
+
:disabled="currentPage * pageSize >= filteredPayments.length"
|
167
|
+
class="px-3 py-1 text-sm bg-white dark:bg-gray-700 border border-gray-300 dark:border-gray-600 rounded-md disabled:opacity-50">
|
168
|
+
Next
|
169
|
+
</button>
|
170
|
+
</div>
|
171
|
+
</div>
|
172
|
+
</div>
|
242
173
|
</div>
|
243
174
|
</div>
|
244
175
|
{% endblock %}
|
245
176
|
|
246
177
|
{% block extra_js %}
|
247
|
-
<script>
|
248
|
-
function paymentList() {
|
249
|
-
return {
|
250
|
-
loading: false,
|
251
|
-
payments: [],
|
252
|
-
totalCount: 0,
|
253
|
-
currentPage: 1,
|
254
|
-
totalPages: 1,
|
255
|
-
filters: {
|
256
|
-
search: '',
|
257
|
-
status: '',
|
258
|
-
provider: '',
|
259
|
-
dateRange: ''
|
260
|
-
},
|
261
|
-
notification: {
|
262
|
-
show: false,
|
263
|
-
type: 'info',
|
264
|
-
message: ''
|
265
|
-
},
|
266
|
-
|
267
|
-
init() {
|
268
|
-
this.loadPayments();
|
269
|
-
},
|
270
|
-
|
271
|
-
async loadPayments() {
|
272
|
-
this.loading = true;
|
273
|
-
try {
|
274
|
-
// Simulate API call - replace with actual endpoint
|
275
|
-
await new Promise(resolve => setTimeout(resolve, 500));
|
276
|
-
|
277
|
-
// Mock data - replace with actual API response
|
278
|
-
this.payments = [
|
279
|
-
{
|
280
|
-
id: '123e4567-e89b-12d3-a456-426614174000',
|
281
|
-
external_id: 'PAY_001',
|
282
|
-
amount_usd: 100.00,
|
283
|
-
amount_crypto: '0.00234',
|
284
|
-
currency_code: 'BTC',
|
285
|
-
status: 'completed',
|
286
|
-
provider: 'nowpayments',
|
287
|
-
created_at: new Date().toISOString()
|
288
|
-
},
|
289
|
-
{
|
290
|
-
id: '123e4567-e89b-12d3-a456-426614174001',
|
291
|
-
external_id: 'PAY_002',
|
292
|
-
amount_usd: 50.00,
|
293
|
-
amount_crypto: null,
|
294
|
-
currency_code: 'USD',
|
295
|
-
status: 'pending',
|
296
|
-
provider: 'stripe',
|
297
|
-
created_at: new Date(Date.now() - 86400000).toISOString()
|
298
|
-
}
|
299
|
-
];
|
300
|
-
this.totalCount = this.payments.length;
|
301
|
-
this.totalPages = Math.ceil(this.totalCount / 20);
|
302
|
-
} catch (error) {
|
303
|
-
this.showNotification('error', 'Failed to load payments');
|
304
|
-
} finally {
|
305
|
-
this.loading = false;
|
306
|
-
}
|
307
|
-
},
|
308
|
-
|
309
|
-
async applyFilters() {
|
310
|
-
this.currentPage = 1;
|
311
|
-
await this.loadPayments();
|
312
|
-
},
|
313
|
-
|
314
|
-
resetFilters() {
|
315
|
-
this.filters = {
|
316
|
-
search: '',
|
317
|
-
status: '',
|
318
|
-
provider: '',
|
319
|
-
dateRange: ''
|
320
|
-
};
|
321
|
-
this.applyFilters();
|
322
|
-
},
|
323
|
-
|
324
|
-
hasActiveFilters() {
|
325
|
-
return Object.values(this.filters).some(value => value !== '');
|
326
|
-
},
|
327
|
-
|
328
|
-
async goToPage(page) {
|
329
|
-
if (page >= 1 && page <= this.totalPages) {
|
330
|
-
this.currentPage = page;
|
331
|
-
await this.loadPayments();
|
332
|
-
}
|
333
|
-
},
|
334
|
-
|
335
|
-
getStatusIcon(status) {
|
336
|
-
const icons = {
|
337
|
-
completed: 'check_circle',
|
338
|
-
pending: 'schedule',
|
339
|
-
processing: 'sync',
|
340
|
-
failed: 'error',
|
341
|
-
cancelled: 'cancel'
|
342
|
-
};
|
343
|
-
return icons[status] || 'help';
|
344
|
-
},
|
345
|
-
|
346
|
-
formatDate(dateString) {
|
347
|
-
const date = new Date(dateString);
|
348
|
-
return date.toLocaleDateString() + ' ' + date.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
|
349
|
-
},
|
350
|
-
|
351
|
-
async copyPaymentId(paymentId) {
|
352
|
-
try {
|
353
|
-
await navigator.clipboard.writeText(paymentId);
|
354
|
-
this.showNotification('success', 'Payment ID copied to clipboard');
|
355
|
-
} catch (error) {
|
356
|
-
this.showNotification('error', 'Failed to copy payment ID');
|
357
|
-
}
|
358
|
-
},
|
359
|
-
|
360
|
-
async exportPayments() {
|
361
|
-
this.loading = true;
|
362
|
-
try {
|
363
|
-
// Simulate export - replace with actual implementation
|
364
|
-
await new Promise(resolve => setTimeout(resolve, 1000));
|
365
|
-
this.showNotification('success', 'Payments exported successfully');
|
366
|
-
} catch (error) {
|
367
|
-
this.showNotification('error', 'Failed to export payments');
|
368
|
-
} finally {
|
369
|
-
this.loading = false;
|
370
|
-
}
|
371
|
-
},
|
372
|
-
|
373
|
-
showNotification(type, message) {
|
374
|
-
this.notification = { show: true, type, message };
|
375
|
-
setTimeout(() => {
|
376
|
-
this.notification.show = false;
|
377
|
-
}, 5000);
|
378
|
-
}
|
379
|
-
};
|
380
|
-
}
|
381
|
-
</script>
|
178
|
+
<script src="{% static 'payments/js/payment-list.js' %}"></script>
|
382
179
|
{% endblock %}
|