| let currentUser = null; |
|
|
| document.addEventListener('DOMContentLoaded', function() { |
| checkAuth(); |
| loadUserProfile(); |
| loadRecentActivity(); |
| setInterval(loadRecentActivity, 30000); |
| }); |
|
|
| function checkAuth() { |
| const token = localStorage.getItem('dashx_token'); |
| const user = JSON.parse(localStorage.getItem('dashx_user') || '{}'); |
|
|
| if (!token) { |
| window.location.href = '/auth'; |
| return; |
| } |
|
|
| currentUser = user; |
| } |
|
|
| async function updateCustomApiKey() { |
| const customApiKey = document.getElementById('customApiKeyInput').value.trim(); |
|
|
| if (!customApiKey) { |
| Swal.fire({ |
| icon: "error", |
| title: "Missing API Key", |
| text: "Please enter a custom API key" |
| }); |
| return; |
| } |
|
|
| try { |
| const token = localStorage.getItem('dashx_token'); |
| const response = await fetch('/api/user/profile', { |
| method: 'PUT', |
| headers: { |
| 'Content-Type': 'application/json', |
| 'Authorization': `Bearer ${token}` |
| }, |
| body: JSON.stringify({ customApiKey }) |
| }); |
|
|
| const result = await response.json(); |
|
|
| if (result.success) { |
| Swal.fire({ |
| title: "API Key Updated!", |
| text: "Your custom API key has been set successfully", |
| icon: "success" |
| }); |
| document.getElementById('customApiKeyInput').value = ''; |
| loadUserProfile(); |
| loadRecentActivity(); |
| } else { |
| Swal.fire({ |
| icon: "error", |
| title: "Update Failed", |
| text: result.error |
| }); |
| } |
| } catch (error) { |
| Swal.fire({ |
| icon: "error", |
| title: "Network Error", |
| text: "Please try again later" |
| }); |
| } |
| } |
|
|
| async function loadUserProfile() { |
| try { |
| const token = localStorage.getItem('dashx_token'); |
| const response = await fetch('/api/user/profile', { |
| headers: { 'Authorization': `Bearer ${token}` } |
| }); |
|
|
| if (response.ok) { |
| const result = await response.json(); |
| if (result.success) { |
| const user = result.user; |
| updateProfileDisplay(user); |
| } |
| } else { |
| logout(); |
| } |
| } catch (error) { |
| console.error('Error loading profile:', error); |
| logout(); |
| } |
| } |
|
|
| async function loadRecentActivity() { |
| try { |
| const token = localStorage.getItem('dashx_token'); |
| const response = await fetch('/api/user/activities', { |
| headers: { 'Authorization': `Bearer ${token}` } |
| }); |
|
|
| if (response.ok) { |
| const result = await response.json(); |
| if (result.success) { |
| updateRecentActivity(result.activities); |
| } |
| } |
| } catch (error) { |
| console.error('Error loading activities:', error); |
| } |
| } |
|
|
| function updateRecentActivity(activities) { |
| const activityList = document.getElementById('recentActivity'); |
|
|
| if (activities.length === 0) { |
| activityList.innerHTML = ` |
| <div class="activity-item"> |
| <i class="fas fa-info-circle" style="color: #74b9ff;"></i> |
| <span>No recent activity</span> |
| </div> |
| `; |
| return; |
| } |
|
|
| const activityIcons = { |
| 'api_key_generated': 'fas fa-key', |
| 'limit_updated': 'fas fa-chart-line', |
| 'profile_updated': 'fas fa-user-edit', |
| 'redeem_code_used': 'fas fa-gift', |
| 'premium_activated': 'fas fa-crown', |
| 'api_request': 'fas fa-code' |
| }; |
|
|
| activityList.innerHTML = activities.map(activity => ` |
| <div class="activity-item"> |
| <i class="${activityIcons[activity.type] || 'fas fa-circle'}" style="color: #853030;"></i> |
| <div style="flex: 1;"> |
| <span>${activity.description}</span> |
| <small style="display: block; opacity: 0.7; margin-top: 0.2rem;">${activity.timeAgo}</small> |
| </div> |
| </div> |
| `).join(''); |
| } |
|
|
| function updateProfileDisplay(user) { |
| const usernameEl = document.getElementById('profileUsername'); |
| const emailEl = document.getElementById('profileEmail'); |
| const apikeyEl = document.getElementById('profileApiKey'); |
| const requestsEl = document.getElementById('profileRequests'); |
| const todayEl = document.getElementById('profileRequestsToday'); |
| const limitEl = document.getElementById('profileLimit'); |
| const roleEl = document.getElementById('profileRole'); |
| const premiumBadge = document.getElementById('premiumBadge'); |
| const adminBadge = document.getElementById('adminBadge'); |
| const profileImage = document.getElementById('profileImage'); |
| const defaultAvatar = document.getElementById('defaultAvatar'); |
|
|
| if (usernameEl) usernameEl.textContent = user.username; |
| if (emailEl) emailEl.textContent = user.email; |
| if (apikeyEl) apikeyEl.textContent = user.apikey; |
| if (requestsEl) requestsEl.textContent = user.requests; |
| if (todayEl) todayEl.textContent = user.requestsToday; |
|
|
| if (user.profileUrl && profileImage && defaultAvatar) { |
| profileImage.src = user.profileUrl; |
| profileImage.style.display = 'block'; |
| defaultAvatar.style.display = 'none'; |
|
|
| profileImage.onerror = function() { |
| profileImage.style.display = 'none'; |
| defaultAvatar.style.display = 'block'; |
| }; |
| } |
|
|
| if (limitEl) { |
| if (user.role === 'admin' && user.limit >= 9999) { |
| limitEl.textContent = '9999'; |
| limitEl.style.fontSize = '2rem'; |
| limitEl.style.color = '#853030'; |
| } else { |
| limitEl.textContent = user.limit; |
| } |
| } |
|
|
| if (roleEl) { |
| roleEl.className = 'badge'; |
|
|
| if (user.role === 'admin') { |
| roleEl.innerHTML = '<i class="fas fa-crown"></i> Admin'; |
| roleEl.classList.add('admin'); |
| if (adminBadge) adminBadge.style.display = 'inline-block'; |
| } else { |
| if (user.userRole) { |
| switch(user.userRole) { |
| case 'cheap': |
| roleEl.innerHTML = '<i class="fas fa-tag"></i> Cheap'; |
| roleEl.classList.add('cheap', 'glow-cheap'); |
| break; |
| case 'premium': |
| roleEl.innerHTML = '<i class="fas fa-star"></i> Premium'; |
| roleEl.classList.add('premium', 'glow-premium'); |
| break; |
| case 'vip': |
| roleEl.innerHTML = '<i class="fas fa-gem"></i> VIP'; |
| roleEl.classList.add('vip', 'glow-vip'); |
| break; |
| case 'supreme': |
| roleEl.innerHTML = '<i class="fas fa-fire"></i> Supreme'; |
| roleEl.classList.add('supreme', 'glow-supreme'); |
| break; |
| default: |
| roleEl.innerHTML = '<i class="fas fa-user"></i> User'; |
| roleEl.classList.add('user'); |
| } |
| } else { |
| roleEl.innerHTML = '<i class="fas fa-user"></i> User'; |
| roleEl.classList.add('user'); |
| } |
| } |
| } |
|
|
| if (user.premium || user.role === 'admin' || user.userRole) { |
| if (premiumBadge) { |
| premiumBadge.style.display = 'inline-block'; |
| premiumBadge.innerHTML = '<i class="fas fa-certificate"></i> Premium'; |
| } |
| const premiumFeatures = document.getElementById('premiumFeatures'); |
| if (premiumFeatures) premiumFeatures.style.display = 'block'; |
| } |
|
|
| if (user.roleExpiresAt) { |
| const expiryDiv = document.getElementById('roleExpiry'); |
| const expiryDate = document.getElementById('roleExpiryDate'); |
| if (expiryDiv && expiryDate) { |
| expiryDiv.style.display = 'block'; |
| const expDate = new Date(user.roleExpiresAt); |
| expiryDate.textContent = expDate.toLocaleDateString('en-US', { |
| year: 'numeric', |
| month: 'long', |
| day: 'numeric' |
| }); |
|
|
| const daysLeft = Math.ceil((expDate - new Date()) / (1000 * 60 * 60 * 24)); |
| if (daysLeft <= 7) { |
| expiryDiv.style.color = '#ff6b6b'; |
| expiryDiv.innerHTML = `<i class="fas fa-exclamation-triangle"></i> Expires in ${daysLeft} days: <span id="roleExpiryDate"></span>`; |
| document.getElementById('roleExpiryDate').textContent = expDate.toLocaleDateString('en-US', { |
| year: 'numeric', |
| month: 'long', |
| day: 'numeric' |
| }); |
| } |
| } |
| } |
|
|
| updateUsageProgress(user.requestsToday, user.limit); |
| } |
|
|
| function updateUsageProgress(current, limit) { |
| const progressFill = document.getElementById('usageProgress'); |
| const progressText = document.getElementById('usageText'); |
|
|
| if (!progressFill || !progressText) return; |
|
|
| if (limit >= 9999) { |
| progressFill.style.width = '0%'; |
| progressFill.style.background = 'linear-gradient(90deg, #853030, #292727)'; |
| progressText.textContent = `${current} / 9999`; |
| return; |
| } |
|
|
| const percentage = Math.min((current / limit) * 100, 100); |
| progressFill.style.width = percentage + '%'; |
| progressText.textContent = `${current} / ${limit}`; |
|
|
| if (percentage >= 90) { |
| progressFill.style.background = 'linear-gradient(90deg, #ff6b6b, #ee5a52)'; |
| } else if (percentage >= 70) { |
| progressFill.style.background = 'linear-gradient(90deg, #f093fb, #f5576c)'; |
| } else { |
| progressFill.style.background = 'linear-gradient(90deg, #853030, #292727)'; |
| } |
| } |
|
|
| function copyApiKey() { |
| const apiKey = document.getElementById('profileApiKey').textContent; |
| navigator.clipboard.writeText(apiKey).then(() => { |
| Swal.fire({ |
| title: "Copied!", |
| text: "API key copied to clipboard", |
| icon: "success", |
| timer: 1500, |
| showConfirmButton: false |
| }); |
| }).catch(() => { |
| Swal.fire({ |
| icon: "error", |
| title: "Copy Failed", |
| text: "Could not copy to clipboard" |
| }); |
| }); |
| } |
|
|
| async function updateUsername() { |
| const newUsername = document.getElementById('newUsername').value.trim(); |
|
|
| if (!newUsername) { |
| Swal.fire({ |
| icon: "error", |
| title: "Missing Username", |
| text: "Please enter a new username" |
| }); |
| return; |
| } |
|
|
| try { |
| const token = localStorage.getItem('dashx_token'); |
| const response = await fetch('/api/user/profile', { |
| method: 'PUT', |
| headers: { |
| 'Content-Type': 'application/json', |
| 'Authorization': `Bearer ${token}` |
| }, |
| body: JSON.stringify({ username: newUsername }) |
| }); |
|
|
| const result = await response.json(); |
|
|
| if (result.success) { |
| Swal.fire({ |
| title: "Username Updated!", |
| text: "Your username has been updated successfully", |
| icon: "success" |
| }); |
| document.getElementById('newUsername').value = ''; |
| loadUserProfile(); |
| loadRecentActivity(); |
| } else { |
| Swal.fire({ |
| icon: "error", |
| title: "Update Failed", |
| text: result.error |
| }); |
| } |
| } catch (error) { |
| Swal.fire({ |
| icon: "error", |
| title: "Network Error", |
| text: "Please try again later" |
| }); |
| } |
| } |
|
|
| async function updateProfileUrl() { |
| const profileUrl = document.getElementById('profileUrlInput').value.trim(); |
|
|
| try { |
| const token = localStorage.getItem('dashx_token'); |
| const response = await fetch('/api/user/profile', { |
| method: 'PUT', |
| headers: { |
| 'Content-Type': 'application/json', |
| 'Authorization': `Bearer ${token}` |
| }, |
| body: JSON.stringify({ profileUrl }) |
| }); |
|
|
| const result = await response.json(); |
|
|
| if (result.success) { |
| Swal.fire({ |
| title: "Profile Updated!", |
| text: "Your profile picture has been updated successfully", |
| icon: "success" |
| }); |
| document.getElementById('profileUrlInput').value = ''; |
| loadUserProfile(); |
| loadRecentActivity(); |
| } else { |
| Swal.fire({ |
| icon: "error", |
| title: "Update Failed", |
| text: result.error |
| }); |
| } |
| } catch (error) { |
| Swal.fire({ |
| icon: "error", |
| title: "Network Error", |
| text: "Please try again later" |
| }); |
| } |
| } |
|
|
| async function regenerateApiKey() { |
| const result = await Swal.fire({ |
| title: "Are you sure?", |
| text: "This will generate a new API key and invalidate the current one!", |
| icon: "warning", |
| showCancelButton: true, |
| confirmButtonColor: "#853030", |
| cancelButtonColor: "#292727", |
| confirmButtonText: "Yes, generate new key!", |
| cancelButtonText: "Cancel" |
| }); |
|
|
| if (result.isConfirmed) { |
| try { |
| const token = localStorage.getItem('dashx_token'); |
| const response = await fetch('/api/user/regenerate-key', { |
| method: 'POST', |
| headers: { 'Authorization': `Bearer ${token}` } |
| }); |
|
|
| const apiResult = await response.json(); |
|
|
| if (apiResult.success) { |
| Swal.fire({ |
| title: "Key Regenerated!", |
| text: `New API Key: ${apiResult.apikey}`, |
| icon: "success" |
| }); |
| loadUserProfile(); |
| loadRecentActivity(); |
| } else { |
| Swal.fire({ |
| title: "Failed!", |
| text: apiResult.error, |
| icon: "error" |
| }); |
| } |
| } catch (error) { |
| Swal.fire({ |
| title: "Error!", |
| text: "Network error occurred", |
| icon: "error" |
| }); |
| } |
| } |
| } |
|
|
| async function deleteAccount() { |
| const result = await Swal.fire({ |
| title: "Are you sure?", |
| text: "You won't be able to revert this!", |
| icon: "warning", |
| showCancelButton: true, |
| confirmButtonColor: "#ff6b6b", |
| cancelButtonColor: "#853030", |
| confirmButtonText: "Yes, delete it!", |
| cancelButtonText: "Cancel" |
| }); |
|
|
| if (result.isConfirmed) { |
| try { |
| const token = localStorage.getItem('dashx_token'); |
| const response = await fetch('/api/user/account', { |
| method: 'DELETE', |
| headers: { 'Authorization': `Bearer ${token}` } |
| }); |
|
|
| const apiResult = await response.json(); |
|
|
| if (apiResult.success) { |
| await Swal.fire({ |
| title: "Account Deleted!", |
| text: "Your account has been deleted.", |
| icon: "success" |
| }); |
| logout(); |
| } else { |
| Swal.fire({ |
| title: "Failed!", |
| text: apiResult.error, |
| icon: "error" |
| }); |
| } |
| } catch (error) { |
| Swal.fire({ |
| title: "Error!", |
| text: "Network error occurred", |
| icon: "error" |
| }); |
| } |
| } |
| } |
|
|
| function logout() { |
| localStorage.removeItem('dashx_token'); |
| localStorage.removeItem('dashx_user'); |
| window.location.href = '/'; |
| } |