Linux spg1.cloudpowerdns.com 5.14.0-611.34.1.el9_7.x86_64 #1 SMP PREEMPT_DYNAMIC Wed Feb 18 05:51:10 EST 2026 x86_64
LiteSpeed
Server IP : 176.9.63.151 & Your IP : 216.73.217.60
Domains :
Cant Read [ /etc/named.conf ]
User : fastear1
Terminal
Auto Root
Create File
Create Folder
Localroot Suggester
Backdoor Destroyer
Readme
/
home /
fastear1 /
.trash /
public /
Delete
Unzip
Name
Size
Permission
Date
Action
data
[ DIR ]
drwxr-xr-x
2025-09-15 23:22
uploads
[ DIR ]
drwxr-xr-x
2025-09-15 18:00
COMPLETE_SETUP_GUIDE.md
5.02
KB
-rw-r--r--
2025-09-15 23:45
DATABASE_SETUP.md
2.84
KB
-rw-r--r--
2025-09-15 23:41
FIX_ACCESS_DENIED.md
2.36
KB
-rw-r--r--
2025-09-16 00:07
MIGRATION_SUMMARY.md
4.28
KB
-rw-r--r--
2025-09-15 23:45
NEXT_STEPS.md
2.18
KB
-rw-r--r--
2025-09-15 23:45
PHPMYADMIN_SETUP_GUIDE.md
3.61
KB
-rw-r--r--
2025-09-15 23:43
QUICK_FIX_INSTRUCTIONS.md
1.99
KB
-rw-r--r--
2025-09-16 00:09
admin-dashboard.html
25.26
KB
-rw-r--r--
2025-09-15 17:29
admin-login.html
5.25
KB
-rw-r--r--
2025-09-15 02:24
admin-profile.html
24.21
KB
-rw-r--r--
2025-09-15 17:43
analytics.html
25.08
KB
-rw-r--r--
2025-09-15 16:13
check_mysql.php
1.33
KB
-rw-r--r--
2025-09-15 23:44
cleanup_duplicates.php
1.46
KB
-rw-r--r--
2025-09-15 23:08
complete_workflow_test.php
4.46
KB
-rw-r--r--
2025-09-15 23:22
create_test_user.php
1.15
KB
-rw-r--r--
2025-09-15 23:20
database.php
4.29
KB
-rw-r--r--
2025-09-15 23:43
database_mysql.php
9.98
KB
-rw-r--r--
2025-09-16 00:08
db_config.php
587
B
-rw-r--r--
2025-09-16 00:07
demo-enhanced.html
45.46
KB
-rw-r--r--
2025-09-15 01:43
deposit.html
10.83
KB
-rw-r--r--
2025-09-15 17:08
error_log
825
B
-rw-r--r--
2025-10-04 15:48
fastearnads.sql
6.12
KB
-rw-r--r--
2025-09-15 23:39
fastearnads_tables_only.sql
5.96
KB
-rw-r--r--
2025-09-16 00:07
final_test.php
4.73
KB
-rw-r--r--
2025-09-15 23:29
import_database.bat
1.03
KB
-rw-r--r--
2025-09-15 23:45
index.php
50.11
KB
-rw-r--r--
2025-09-15 23:40
manage-ads.html
25.39
KB
-rw-r--r--
2025-09-15 16:12
manage-users.html
42.4
KB
-rw-r--r--
2025-09-15 16:54
manage-withdraws.html
49.19
KB
-rw-r--r--
2025-09-15 15:54
migrate_data.php
1.6
KB
-rw-r--r--
2025-09-15 23:40
simple-login.html
1.19
KB
-rw-r--r--
2025-09-15 02:08
start_mysql.bat
948
B
-rw-r--r--
2025-09-15 23:45
test_admin_approval.php
3.55
KB
-rw-r--r--
2025-09-15 23:21
test_connection_with_user.php
1.9
KB
-rw-r--r--
2025-09-15 19:19
test_db_connection.php
1.54
KB
-rw-r--r--
2025-09-15 23:41
test_deposit_fix.php
2.88
KB
-rw-r--r--
2025-09-15 23:09
test_frontend.html
3.49
KB
-rw-r--r--
2025-09-15 23:22
test_user_activity_history.php
2.96
KB
-rw-r--r--
2025-09-15 23:21
user-ads.html
18.36
KB
-rw-r--r--
2025-09-15 14:39
user-dashboard.html
47.77
KB
-rw-r--r--
2025-09-15 23:26
user-login.html
5.78
KB
-rw-r--r--
2025-09-15 02:27
user-profile.html
33.93
KB
-rw-r--r--
2025-09-15 18:33
user-register.html
7.56
KB
-rw-r--r--
2025-09-15 02:27
user-transactions.html
31.83
KB
-rw-r--r--
2025-09-15 22:58
user-withdraw.html
29.48
KB
-rw-r--r--
2025-09-15 21:52
user-withdrawals.html
29.17
KB
-rw-r--r--
2025-09-15 21:51
waiting-approval.html
5.46
KB
-rw-r--r--
2025-09-15 03:23
Save
Rename
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Manage Users - FastEarnAds Admin</title> <script src="https://cdn.tailwindcss.com"></script> <script defer src="https://unpkg.com/alpinejs@3.x.x/dist/cdn.min.js"></script> <style> [x-cloak] { display: none !important; } .modal-enter { animation: modalEnter 0.3s ease-out; } @keyframes modalEnter { from { opacity: 0; transform: scale(0.9) translateY(-10px); } to { opacity: 1; transform: scale(1) translateY(0); } } .user-avatar { animation: avatarPulse 2s ease-in-out infinite; } @keyframes avatarPulse { 0%, 100% { box-shadow: 0 0 0 0 rgba(99, 102, 241, 0.4); } 50% { box-shadow: 0 0 0 10px rgba(99, 102, 241, 0); } } </style> </head> <body class="bg-gray-50" x-data="usersData()" x-init="loadUsers()"> <!-- Header --> <header class="bg-white shadow-sm border-b border-gray-200"> <div class="max-w-7xl mx-auto px-4 py-4"> <div class="flex items-center justify-between"> <div class="flex items-center space-x-4"> <div class="w-10 h-10 bg-gradient-to-r from-blue-600 to-purple-600 rounded-lg flex items-center justify-center"> <svg class="w-6 h-6 text-white" fill="none" viewBox="0 0 24 24" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4.354a4 4 0 110 5.292M15 21H3v-1a6 6 0 0112 0v1zm0 0h6v-1a6 6 0 00-9-5.197m13.5-9a2.5 2.5 0 11-5 0 2.5 2.5 0 015 0z"/> </svg> </div> <div> <h1 class="text-xl font-bold text-gray-900">Manage Users</h1> <p class="text-sm text-gray-600">FastEarnAds Admin Panel</p> </div> </div> <button onclick="window.location.href='/admin/dashboard'" class="bg-gray-600 text-white px-4 py-2 rounded-lg hover:bg-gray-700"> Back to Dashboard </button> </div> </div> </header> <!-- Main Content --> <div class="max-w-7xl mx-auto px-4 py-8"> <div class="bg-white rounded-xl shadow-sm border overflow-hidden"> <div class="px-6 py-4 border-b border-gray-200"> <h3 class="text-lg font-semibold text-gray-900">All Registered Users</h3> <p class="text-sm text-gray-600 mt-1">Total Users: <span x-text="allUsers.length"></span></p> </div> <div class="overflow-x-auto"> <table class="min-w-full divide-y divide-gray-200"> <thead class="bg-gray-50"> <tr> <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">User</th> <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Contact</th> <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Balance</th> <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Status</th> <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Joined</th> <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Actions</th> </tr> </thead> <tbody class="bg-white divide-y divide-gray-200"> <template x-for="user in allUsers" :key="user.id"> <tr> <td class="px-6 py-4 whitespace-nowrap"> <div class="flex items-center"> <img class="h-10 w-10 rounded-full" :src="'https://ui-avatars.com/api/?name=' + encodeURIComponent(user.name) + '&background=6366f1&color=fff'" :alt="user.name"> <div class="ml-4"> <div class="text-sm font-medium text-gray-900" x-text="user.name"></div> <div class="text-sm text-gray-500" x-text="user.email"></div> </div> </div> </td> <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900" x-text="user.phone || 'N/A'"></td> <td class="px-6 py-4 whitespace-nowrap"> <div class="flex items-center space-x-2"> <span class="text-sm font-medium text-green-600" x-text="'$' + (user.balance || 0).toFixed(2)"></span> <button @click.stop="openBalanceModal(user)" class="text-xs bg-blue-100 text-blue-800 px-2 py-1 rounded hover:bg-blue-200"> Edit </button> </div> </td> <td class="px-6 py-4 whitespace-nowrap"> <span x-text="user.deposit_status || 'pending'" :class="{ 'bg-green-100 text-green-800': user.deposit_status === 'approved', 'bg-yellow-100 text-yellow-800': user.deposit_status === 'waiting', 'bg-red-100 text-red-800': user.deposit_status === 'pending' }" class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full capitalize"></span> </td> <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500" x-text="formatDate(user.created_at)"></td> <td class="px-6 py-4 whitespace-nowrap text-sm font-medium"> <div class="flex flex-wrap gap-2"> <button @click.stop="viewUserDetails(user)" class="text-indigo-600 hover:text-indigo-900">View</button> <button @click.stop="openBalanceModal(user)" class="text-green-600 hover:text-green-900">Balance</button> <button @click.stop="activateAccount(user)" x-show="user.deposit_status !== 'approved'" class="text-emerald-600 hover:text-emerald-900 font-medium">Activate</button> <button @click.stop="deleteUser(user.id)" class="text-red-600 hover:text-red-900">Delete</button> </div> </td> </tr> </template> </tbody> </table> <div x-show="allUsers.length === 0" class="text-center py-12"> <svg class="w-16 h-16 mx-auto mb-4 text-gray-300" fill="none" viewBox="0 0 24 24" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4.354a4 4 0 110 5.292M15 21H3v-1a6 6 0 0112 0v1zm0 0h6v-1a6 6 0 00-9-5.197m13.5-9a2.5 2.5 0 11-5 0 2.5 2.5 0 015 0z"/> </svg> <h3 class="text-lg font-medium text-gray-900 mb-2">No Users Found</h3> <p class="text-gray-600">No users have registered yet.</p> </div> </div> </div> </div> <!-- User Details Modal --> <div x-show="showUserModal" x-cloak class="fixed inset-0 z-50 flex items-center justify-center px-4 py-6"> <div class="fixed inset-0 bg-black bg-opacity-50 backdrop-blur-sm transition-opacity" x-show="showUserModal" x-transition:enter="ease-out duration-300" x-transition:enter-start="opacity-0" x-transition:enter-end="opacity-100" x-transition:leave="ease-in duration-200" x-transition:leave-start="opacity-100" x-transition:leave-end="opacity-0" @click.stop="closeUserModal()"></div> <div class="relative bg-white rounded-2xl shadow-2xl max-w-4xl w-full mx-auto modal-enter" x-show="showUserModal" x-transition:enter="ease-out duration-300" x-transition:enter-start="opacity-0 scale-95 translate-y-4" x-transition:enter-end="opacity-100 scale-100 translate-y-0" x-transition:leave="ease-in duration-200" x-transition:leave-start="opacity-100 scale-100 translate-y-0" x-transition:leave-end="opacity-0 scale-95 translate-y-4"> <!-- Header --> <div class="bg-gradient-to-r from-blue-600 to-purple-600 text-white px-6 py-4 rounded-t-2xl"> <div class="flex items-center justify-between"> <div class="flex items-center space-x-4"> <img class="w-16 h-16 rounded-full border-4 border-white user-avatar" :src="'https://ui-avatars.com/api/?name=' + encodeURIComponent(selectedUser?.name || 'User') + '&background=ffffff&color=6366f1&size=64'" :alt="selectedUser?.name"> <div> <h3 class="text-xl font-bold" x-text="selectedUser?.name">User Details</h3> <p class="text-blue-100 text-sm" x-text="selectedUser?.email">user@example.com</p> </div> </div> <button @click.stop="closeUserModal()" class="text-white hover:text-gray-200 p-2 rounded-lg hover:bg-white hover:bg-opacity-20 transition-all"> <svg class="w-6 h-6" fill="none" viewBox="0 0 24 24" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/> </svg> </button> </div> </div> <!-- Content --> <div class="p-6" x-show="selectedUser"> <div class="grid grid-cols-1 lg:grid-cols-2 gap-8"> <!-- Personal Information --> <div class="bg-gradient-to-br from-gray-50 to-blue-50 rounded-xl p-6"> <h4 class="text-lg font-semibold text-gray-900 mb-6 flex items-center"> <svg class="w-5 h-5 mr-2 text-blue-600" fill="none" viewBox="0 0 24 24" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z"/> </svg> Personal Information </h4> <div class="space-y-4"> <div class="bg-white rounded-lg p-4 shadow-sm"> <label class="text-sm font-medium text-gray-600 uppercase tracking-wider">Full Name</label> <p class="text-lg font-semibold text-gray-900 mt-1" x-text="selectedUser?.name">-</p> </div> <div class="bg-white rounded-lg p-4 shadow-sm"> <label class="text-sm font-medium text-gray-600 uppercase tracking-wider">Email Address</label> <p class="text-lg font-medium text-gray-900 mt-1" x-text="selectedUser?.email">-</p> </div> <div class="bg-white rounded-lg p-4 shadow-sm"> <label class="text-sm font-medium text-gray-600 uppercase tracking-wider">Phone Number</label> <p class="text-lg font-medium text-gray-900 mt-1" x-text="selectedUser?.phone || 'Not provided'">-</p> </div> <div class="bg-white rounded-lg p-4 shadow-sm"> <label class="text-sm font-medium text-gray-600 uppercase tracking-wider">Account Status</label> <div class="mt-2"> <span x-text="selectedUser?.deposit_status || 'pending'" :class="{ 'bg-green-100 text-green-800 border-green-200': selectedUser?.deposit_status === 'approved', 'bg-yellow-100 text-yellow-800 border-yellow-200': selectedUser?.deposit_status === 'waiting', 'bg-red-100 text-red-800 border-red-200': selectedUser?.deposit_status === 'pending' }" class="px-3 py-2 text-sm font-semibold rounded-lg border capitalize inline-block"></span> </div> </div> </div> </div> <!-- Account Statistics --> <div class="bg-gradient-to-br from-gray-50 to-green-50 rounded-xl p-6"> <h4 class="text-lg font-semibold text-gray-900 mb-6 flex items-center"> <svg class="w-5 h-5 mr-2 text-green-600" fill="none" viewBox="0 0 24 24" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v4a2 2 0 01-2 2H9a2 2 0 00-2 2z"/> </svg> Account Statistics </h4> <div class="grid grid-cols-1 gap-4"> <div class="bg-white rounded-lg p-4 shadow-sm border-l-4 border-green-500"> <label class="text-sm font-medium text-gray-600 uppercase tracking-wider">Current Balance</label> <p class="text-2xl font-bold text-green-600 mt-1" x-text="'$' + (selectedUser?.balance || 0).toFixed(2)">$0.00</p> </div> <div class="bg-white rounded-lg p-4 shadow-sm border-l-4 border-blue-500"> <label class="text-sm font-medium text-gray-600 uppercase tracking-wider">Ads Watched</label> <p class="text-xl font-bold text-blue-600 mt-1" x-text="selectedUser?.ads_watched || 0">0</p> </div> <div class="bg-white rounded-lg p-4 shadow-sm border-l-4 border-purple-500"> <label class="text-sm font-medium text-gray-600 uppercase tracking-wider">Total Earned</label> <p class="text-xl font-bold text-purple-600 mt-1" x-text="'$' + (selectedUser?.total_earned || 0).toFixed(2)">$0.00</p> </div> <div class="bg-white rounded-lg p-4 shadow-sm border-l-4 border-gray-500"> <label class="text-sm font-medium text-gray-600 uppercase tracking-wider">Member Since</label> <p class="text-lg font-medium text-gray-900 mt-1" x-text="formatDate(selectedUser?.created_at)">-</p> </div> </div> </div> </div> </div> <!-- Footer --> <div class="bg-gray-50 px-6 py-4 rounded-b-2xl border-t border-gray-200"> <div class="flex justify-between items-center"> <p class="text-sm text-gray-600">User ID: <span class="font-mono font-medium" x-text="selectedUser?.id">-</span></p> <div class="flex flex-wrap gap-2"> <button @click.stop="activateAccount(selectedUser)" x-show="selectedUser?.deposit_status !== 'approved'" class="bg-emerald-600 text-white px-4 py-2 rounded-lg hover:bg-emerald-700 transition-colors flex items-center"> <svg class="w-4 h-4 mr-2" fill="none" viewBox="0 0 24 24" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"/> </svg> Activate Account </button> <button @click.stop="openBalanceModal(selectedUser)" class="bg-blue-600 text-white px-4 py-2 rounded-lg hover:bg-blue-700 transition-colors flex items-center"> <svg class="w-4 h-4 mr-2" fill="none" viewBox="0 0 24 24" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8c-1.657 0-3 .895-3 2s1.343 2 3 2 3 .895 3 2-1.343 2-3 2m0-8c1.11 0 2.08.402 2.599 1M12 8V7m0 1v8m0 0v1m0-1c-1.11 0-2.08-.402-2.599-1"/> </svg> Manage Balance </button> <button @click.stop="loginAsUser(selectedUser)" class="bg-purple-600 text-white px-4 py-2 rounded-lg hover:bg-purple-700 transition-colors flex items-center"> <svg class="w-4 h-4 mr-2" fill="none" viewBox="0 0 24 24" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11 16l-4-4m0 0l4-4m-4 4h14m-5 4v1a3 3 0 01-3 3H6a3 3 0 01-3-3V7a3 3 0 013-3h7a3 3 0 013 3v1"/> </svg> Login as User </button> <button @click.stop="closeUserModal()" class="bg-gray-600 text-white px-4 py-2 rounded-lg hover:bg-gray-700 transition-colors"> Close </button> </div> </div> </div> </div> </div> <!-- Balance Management Modal --> <div x-show="showBalanceModal && selectedUser && !showUserModal" x-cloak class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-[60]" @click.stop.self="closeBalanceModal()"> <div class="bg-white rounded-xl shadow-xl max-w-md w-full mx-4"> <div class="px-6 py-4 border-b border-gray-200 flex items-center justify-between"> <h3 class="text-lg font-semibold text-gray-900">Manage User Balance</h3> <button @click.stop="closeBalanceModal()" class="text-gray-400 hover:text-gray-600"> <svg class="w-6 h-6" fill="none" viewBox="0 0 24 24" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/> </svg> </button> </div> <div class="p-6" x-show="selectedUser"> <div class="mb-4"> <p class="text-sm text-gray-600">User: <span class="font-medium" x-text="selectedUser?.name"></span></p> <p class="text-sm text-gray-600">Current Balance: <span class="font-bold text-green-600" x-text="'$' + (selectedUser?.balance || 0).toFixed(2)"></span></p> </div> <div class="space-y-4"> <div> <label class="block text-sm font-medium text-gray-700 mb-2">Operation</label> <div class="flex space-x-2"> <button @click="balanceOperation = 'add'" :class="balanceOperation === 'add' ? 'bg-green-600 text-white' : 'bg-gray-200 text-gray-700'" class="flex-1 px-4 py-2 rounded-lg font-medium transition-colors"> Add Balance </button> <button @click="balanceOperation = 'subtract'" :class="balanceOperation === 'subtract' ? 'bg-red-600 text-white' : 'bg-gray-200 text-gray-700'" class="flex-1 px-4 py-2 rounded-lg font-medium transition-colors"> Subtract Balance </button> </div> </div> <div> <label class="block text-sm font-medium text-gray-700 mb-2">Amount ($)</label> <input type="number" x-model="balanceAmount" step="0.01" min="0" class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500" placeholder="Enter amount"> </div> <div> <label class="block text-sm font-medium text-gray-700 mb-2">Reason (Optional)</label> <textarea x-model="balanceReason" rows="3" class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500" placeholder="Enter reason for balance adjustment"></textarea> </div> <div x-show="balanceOperation && balanceAmount" class="bg-gray-50 p-3 rounded-lg"> <p class="text-sm text-gray-600">Preview:</p> <p class="text-sm font-medium"> <span x-text="'Current: $' + (selectedUser?.balance || 0).toFixed(2)"></span> <span x-text="balanceOperation === 'add' ? ' + ' : ' - '"></span> <span x-text="'$' + parseFloat(balanceAmount || 0).toFixed(2)"></span> <span x-text="' = $' + calculateNewBalance().toFixed(2)"></span> </p> </div> </div> <div class="flex space-x-3 mt-6"> <button @click.stop="closeBalanceModal()" class="flex-1 px-4 py-2 bg-gray-300 text-gray-700 rounded-lg hover:bg-gray-400 transition-colors"> Cancel </button> <button @click.stop="updateUserBalance()" :disabled="!balanceOperation || !balanceAmount || processing" :class="!balanceOperation || !balanceAmount || processing ? 'bg-gray-400 cursor-not-allowed' : (balanceOperation === 'add' ? 'bg-green-600 hover:bg-green-700' : 'bg-red-600 hover:bg-red-700')" class="flex-1 px-4 py-2 text-white rounded-lg transition-colors"> <span x-show="!processing" x-text="balanceOperation === 'add' ? 'Add Balance' : 'Subtract Balance'"></span> <span x-show="processing">Processing...</span> </button> </div> </div> </div> </div> <!-- Professional Confirmation Modal --> <div x-show="showConfirmModal" x-cloak class="fixed inset-0 z-[70] flex items-center justify-center px-4 py-6"> <div class="fixed inset-0 bg-black bg-opacity-50 backdrop-blur-sm transition-opacity" x-show="showConfirmModal" x-transition:enter="ease-out duration-300" x-transition:enter-start="opacity-0" x-transition:enter-end="opacity-100" x-transition:leave="ease-in duration-200" x-transition:leave-start="opacity-100" x-transition:leave-end="opacity-0" @click.stop="closeConfirmModal()"></div> <div class="relative bg-white rounded-2xl shadow-2xl max-w-md w-full mx-auto" x-show="showConfirmModal" x-transition:enter="ease-out duration-300" x-transition:enter-start="opacity-0 scale-95 translate-y-4" x-transition:enter-end="opacity-100 scale-100 translate-y-0" x-transition:leave="ease-in duration-200" x-transition:leave-start="opacity-100 scale-100 translate-y-0" x-transition:leave-end="opacity-0 scale-95 translate-y-4"> <!-- Header --> <div :class="confirmModalColor" class="text-white px-6 py-4 rounded-t-2xl"> <div class="flex items-center space-x-3"> <div class="w-10 h-10 bg-white bg-opacity-20 rounded-full flex items-center justify-center"> <svg class="w-6 h-6 text-white" fill="none" viewBox="0 0 24 24" stroke="currentColor" x-html="confirmModalIcon"> </svg> </div> <h3 class="text-lg font-bold" x-text="confirmModalTitle">Confirm Action</h3> </div> </div> <!-- Content --> <div class="p-6"> <p class="text-gray-700 text-sm leading-relaxed" x-text="confirmModalMessage">Are you sure you want to proceed with this action?</p> </div> <!-- Footer --> <div class="bg-gray-50 px-6 py-4 rounded-b-2xl border-t border-gray-200"> <div class="flex space-x-3"> <button @click.stop="closeConfirmModal()" class="flex-1 px-4 py-2 bg-gray-300 text-gray-700 rounded-lg hover:bg-gray-400 transition-colors font-medium"> Cancel </button> <button @click.stop="executeConfirmAction()" :class="confirmModalColor" class="flex-1 px-4 py-2 text-white rounded-lg hover:opacity-90 transition-all font-medium"> Confirm </button> </div> </div> </div> </div> <script> function usersData() { return { allUsers: [], selectedUser: null, showUserModal: false, showBalanceModal: false, showConfirmModal: false, confirmModalTitle: '', confirmModalMessage: '', confirmModalAction: null, confirmModalIcon: '', confirmModalColor: '', balanceOperation: '', balanceAmount: '', balanceReason: '', processing: false, async loadUsers() { try { const response = await fetch('/admin/users'); if (response.ok) { this.allUsers = await response.json(); } } catch (error) { console.error('Error loading users:', error); alert('Error loading users. Please try again.'); } }, formatDate(dateString) { if (!dateString) return 'N/A'; return new Date(dateString).toLocaleDateString(); }, viewUserDetails(user) { // Close balance modal if it's open this.showBalanceModal = false; // Open user details modal this.selectedUser = user; this.showUserModal = true; }, closeUserModal() { this.showUserModal = false; this.showBalanceModal = false; // Ensure balance modal is also closed // Use a small delay to ensure clean state reset setTimeout(() => { this.selectedUser = null; // Reset balance modal state this.balanceOperation = ''; this.balanceAmount = ''; this.balanceReason = ''; }, 100); }, openBalanceModal(user) { // Close user modal first if it's open this.showUserModal = false; // Use a small delay to ensure clean transition setTimeout(() => { // Set up balance modal this.selectedUser = user; this.showBalanceModal = true; this.balanceOperation = ''; this.balanceAmount = ''; this.balanceReason = ''; }, 150); }, closeBalanceModal() { this.showBalanceModal = false; // Use a small delay to ensure clean state reset setTimeout(() => { this.selectedUser = null; this.balanceOperation = ''; this.balanceAmount = ''; this.balanceReason = ''; }, 100); }, calculateNewBalance() { if (!this.selectedUser || !this.balanceAmount) return 0; const currentBalance = this.selectedUser.balance || 0; const amount = parseFloat(this.balanceAmount) || 0; if (this.balanceOperation === 'add') { return currentBalance + amount; } else if (this.balanceOperation === 'subtract') { return Math.max(0, currentBalance - amount); } return currentBalance; }, async updateUserBalance() { if (!this.selectedUser || !this.balanceOperation || !this.balanceAmount) { alert('Please fill in all required fields.'); return; } const amount = parseFloat(this.balanceAmount); if (amount <= 0) { alert('Amount must be greater than 0.'); return; } if (this.balanceOperation === 'subtract' && amount > (this.selectedUser.balance || 0)) { alert('Cannot subtract more than the current balance.'); return; } this.processing = true; try { const response = await fetch('/admin/update-user-balance', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ userId: this.selectedUser.id, userEmail: this.selectedUser.email, operation: this.balanceOperation, amount: amount, reason: this.balanceReason || 'Admin balance adjustment' }) }); const result = await response.json(); if (response.ok && result.success) { // Update the user in the list const userIndex = this.allUsers.findIndex(u => u.id === this.selectedUser.id); if (userIndex !== -1) { this.allUsers[userIndex].balance = result.newBalance; this.selectedUser.balance = result.newBalance; } alert(`Balance ${this.balanceOperation === 'add' ? 'added' : 'subtracted'} successfully! New balance: $${result.newBalance.toFixed(2)}`); this.closeBalanceModal(); } else { alert(result.error || 'Failed to update balance.'); } } catch (error) { console.error('Error updating balance:', error); alert('Error updating balance. Please try again.'); } finally { this.processing = false; } }, async deleteUser(userId) { if (!confirm('Are you sure you want to delete this user? This action cannot be undone.')) { return; } try { const response = await fetch('/admin/delete-user', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ id: userId }) }); const result = await response.json(); if (response.ok && result.success) { // Remove user from the list this.allUsers = this.allUsers.filter(u => u.id !== userId); alert('User deleted successfully.'); } else { alert(result.error || 'Failed to delete user.'); } } catch (error) { console.error('Error deleting user:', error); alert('Error deleting user. Please try again.'); } }, showProfessionalConfirm(title, message, action, iconType = 'warning') { this.confirmModalTitle = title; this.confirmModalMessage = message; this.confirmModalAction = action; // Set icon and color based on type switch (iconType) { case 'success': this.confirmModalIcon = '<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"/>'; this.confirmModalColor = 'bg-gradient-to-r from-green-500 to-emerald-600'; break; case 'danger': this.confirmModalIcon = '<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.964-.833-2.732 0L3.732 16.5c-.77.833.192 2.5 1.732 2.5z"/>'; this.confirmModalColor = 'bg-gradient-to-r from-red-500 to-pink-600'; break; case 'info': this.confirmModalIcon = '<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11 15l-3-3m0 0l3-3m-3 3h8M3 12a9 9 0 1118 0 9 9 0 01-18 0z"/>'; this.confirmModalColor = 'bg-gradient-to-r from-purple-500 to-indigo-600'; break; default: // warning this.confirmModalIcon = '<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.964-.833-2.732 0L3.732 16.5c-.77.833.192 2.5 1.732 2.5z"/>'; this.confirmModalColor = 'bg-gradient-to-r from-orange-500 to-red-500'; } this.showConfirmModal = true; }, closeConfirmModal() { this.showConfirmModal = false; this.confirmModalAction = null; }, executeConfirmAction() { if (this.confirmModalAction) { this.confirmModalAction(); } this.closeConfirmModal(); }, async activateAccount(user) { this.showProfessionalConfirm( '🚀 Activate User Account', `Are you sure you want to fully activate ${user.name}'s account? This will approve their deposit and grant full access to the platform.`, () => this.performActivateAccount(user), 'success' ); }, async performActivateAccount(user) { try { const response = await fetch('/admin/activate-user-account', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ userId: user.id, userEmail: user.email }) }); const result = await response.json(); if (response.ok && result.success) { // Update user status in the list const userIndex = this.allUsers.findIndex(u => u.id === user.id); if (userIndex !== -1) { this.allUsers[userIndex].deposit_status = 'approved'; } // Update selected user if it's the same user if (this.selectedUser && this.selectedUser.id === user.id) { this.selectedUser.deposit_status = 'approved'; } this.showProfessionalConfirm( '✅ Account Activated Successfully!', `${user.name}'s account has been successfully activated! They now have full access to the platform and can start earning.`, () => {}, 'success' ); } else { this.showProfessionalConfirm( '❌ Activation Failed', result.error || 'Failed to activate user account. Please try again.', () => {}, 'danger' ); } } catch (error) { console.error('Error activating user account:', error); this.showProfessionalConfirm( '🚨 Network Error', 'Error activating user account. Please check your connection and try again.', () => {}, 'danger' ); } }, async loginAsUser(user) { this.showProfessionalConfirm( '🔐 Login as User', `Are you sure you want to login as ${user.name}? This will redirect you to their user dashboard and log all your actions for security purposes.`, () => this.performLoginAsUser(user), 'info' ); }, async performLoginAsUser(user) { try { const response = await fetch('/admin/login-as-user', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ userId: user.id, userEmail: user.email }) }); const result = await response.json(); if (response.ok && result.success) { // Redirect to user dashboard window.location.href = result.redirectUrl || '/dashboard'; } else { this.showProfessionalConfirm( '❌ Login Failed', result.error || 'Failed to login as user. Please try again.', () => {}, 'danger' ); } } catch (error) { console.error('Error logging in as user:', error); this.showProfessionalConfirm( '🚨 Network Error', 'Error logging in as user. Please check your connection and try again.', () => {}, 'danger' ); } } } } </script> </body> </html>