| <!DOCTYPE html> |
| <html lang="en"> |
| <head> |
| <meta charset="UTF-8"> |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
| <title>DashX - Modern API Dashboard</title> |
| <meta name="description" content="DashX is a modern REST API dashboard platform that allows you to manage, monitor, and utilize various API tools with ease. Fully featured for developers with an intuitive interface and powerful analytics."> |
| <meta name="keywords" content="API Dashboard, REST API, DashX, API Management, Developer Tools, API Analytics"> |
| <meta name="author" content="DashX Team"> |
| <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" rel="stylesheet"> |
| <link rel="icon" type="image/webp" href="/icon.webp"> |
| <link href="https://cdnjs.cloudflare.com/ajax/libs/sweetalert2/11.10.8/sweetalert2.min.css" rel="stylesheet"> |
| <link href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.0/css/bootstrap.min.css" rel="stylesheet"> |
| <link href="styles.css" rel="stylesheet"> |
| <script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.0/dist/chart.umd.min.js"></script> |
| <style> |
| i.fas, i.fa, i.far, i.fab, i.fal, |
| .fas, .fa, .far, .fab, .fal, |
| i[class*="fa-"] { |
| font-family: "Font Awesome 6 Free", "Font Awesome 6 Pro", "FontAwesome" !important; |
| font-weight: 900 !important; |
| font-style: normal !important; |
| font-variant: normal !important; |
| text-rendering: auto !important; |
| line-height: 1 !important; |
| -webkit-font-smoothing: antialiased !important; |
| -moz-osx-font-smoothing: grayscale !important; |
| display: inline-block !important; |
| } |
| |
| .stat-item { |
| text-align: center; |
| padding: 1.5rem; |
| background: rgba(255, 255, 255, 0.05); |
| border-radius: 12px; |
| border: 1px solid rgba(255, 255, 255, 0.1); |
| } |
| |
| .stat-item .stat-value { |
| display: block; |
| font-size: 1.8rem; |
| font-weight: 700; |
| color: rgba(133, 48, 48, 0.9); |
| margin-bottom: 0.5rem; |
| } |
| |
| .stat-item .stat-label { |
| display: block; |
| font-size: 0.9rem; |
| color: rgba(255, 255, 255, 0.7); |
| } |
| |
| .stat-icon { |
| font-size: 3rem !important; |
| color: rgba(255, 168, 168, 0.9) !important; |
| min-width: 80px !important; |
| text-align: center !important; |
| display: flex !important; |
| align-items: center !important; |
| justify-content: center !important; |
| } |
| |
| .stat-icon i { |
| font-size: 3rem !important; |
| display: block !important; |
| } |
| |
| .stat-info { |
| flex: 1; |
| } |
| |
| .stat-number { |
| font-size: 2rem; |
| font-weight: 700; |
| color: rgba(255, 255, 255, 0.9); |
| margin-bottom: 0.25rem; |
| word-break: break-all; |
| } |
| |
| .stat-label { |
| font-size: 0.9rem; |
| color: rgba(255, 255, 255, 0.7); |
| } |
| |
| .section h2 i { |
| color: #e74c3c !important; |
| } |
| |
| .navbar { |
| background: rgba(44, 62, 80, 0.95) !important; |
| backdrop-filter: blur(10px); |
| border-bottom: 1px solid rgba(255, 255, 255, 0.1); |
| box-shadow: 0 2px 20px rgba(0, 0, 0, 0.2); |
| } |
| |
| .navbar-brand { |
| font-size: 1.5rem; |
| font-weight: 700; |
| color: #fff !important; |
| } |
| |
| .navbar-brand i { |
| color: #e74c3c; |
| font-size: 1.8rem; |
| margin-right: 0.5rem; |
| } |
| |
| .nav-link { |
| color: #ecf0f1 !important; |
| font-weight: 500; |
| transition: all 0.3s ease; |
| padding: 0.5rem 1rem !important; |
| border-radius: 8px; |
| margin: 0 0.25rem; |
| } |
| |
| .nav-link:hover { |
| background: rgba(255, 255, 255, 0.1); |
| transform: translateY(-1px); |
| } |
| |
| .nav-link.text-danger { |
| color: #e74c3c !important; |
| } |
| |
| .nav-link.text-danger:hover { |
| background: rgba(231, 76, 60, 0.1); |
| color: #ff6b6b !important; |
| } |
| |
| .glassmorphism { |
| background: rgba(255, 255, 255, 0.1); |
| backdrop-filter: blur(10px); |
| -webkit-backdrop-filter: blur(10px); |
| border: 1px solid rgba(255, 255, 255, 0.2); |
| border-radius: 16px; |
| box-shadow: 0 8px 32px 0 rgba(31, 38, 135, 0.37); |
| } |
| |
| .reset-timer-card { |
| margin-top: 2rem; |
| padding: 1.5rem; |
| border-radius: 12px; |
| background: rgba(255, 255, 255, 0.05); |
| backdrop-filter: blur(10px); |
| border: 1px solid rgba(255, 255, 255, 0.1); |
| box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1); |
| } |
| |
| .timer-header { |
| display: flex; |
| align-items: center; |
| gap: 1rem; |
| margin-bottom: 1rem; |
| } |
| |
| .timer-header i { |
| font-size: 1.5rem; |
| color: #853030; |
| } |
| |
| .timer-header h3 { |
| margin: 0; |
| font-size: 1.2rem; |
| color: rgba(255, 255, 255, 0.9); |
| } |
| |
| .timer-header p { |
| margin: 0; |
| opacity: 0.7; |
| font-size: 0.9rem; |
| } |
| |
| .countdown-display { |
| text-align: center; |
| padding: 2rem 1rem; |
| } |
| |
| .countdown-time { |
| font-size: 3rem; |
| font-weight: bold; |
| color: #853030; |
| font-family: 'Courier New', monospace; |
| letter-spacing: 0.1em; |
| text-shadow: 0 0 20px rgba(133, 48, 48, 0.3); |
| } |
| |
| .countdown-label { |
| margin-top: 0.5rem; |
| opacity: 0.6; |
| font-size: 0.9rem; |
| color: rgba(255, 255, 255, 0.8); |
| } |
| |
| .reset-progress-container { |
| width: 100%; |
| height: 8px; |
| background: rgba(255, 255, 255, 0.1); |
| border-radius: 4px; |
| overflow: hidden; |
| margin-top: 1rem; |
| } |
| |
| .reset-progress { |
| height: 100%; |
| background: linear-gradient(90deg, #853030, #ff6b6b); |
| transition: width 1s linear; |
| width: 0%; |
| box-shadow: 0 0 10px rgba(133, 48, 48, 0.5); |
| } |
| |
| .reset-info { |
| margin-top: 1rem; |
| padding: 1rem; |
| background: rgba(255, 255, 255, 0.05); |
| border-radius: 8px; |
| display: flex; |
| justify-content: space-between; |
| align-items: center; |
| } |
| |
| .reset-info i { |
| color: #853030; |
| margin-right: 0.5rem; |
| } |
| |
| .reset-info span { |
| font-size: 0.9rem; |
| color: rgba(255, 255, 255, 0.8); |
| } |
| |
| .reset-info div:last-child { |
| font-weight: bold; |
| color: #853030; |
| } |
| |
| @keyframes pulse { |
| 0%, 100% { opacity: 1; } |
| 50% { opacity: 0.7; } |
| } |
| |
| .reset-countdown { |
| animation: pulse 2s ease-in-out infinite; |
| } |
| |
| .usage-overview { |
| display: grid; |
| grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); |
| gap: 1.5rem; |
| margin-top: 1rem; |
| } |
| |
| .usage-section { |
| background: rgba(255, 255, 255, 0.05); |
| backdrop-filter: blur(10px); |
| -webkit-backdrop-filter: blur(10px); |
| border: 1px solid rgba(255, 255, 255, 0.1); |
| padding: 1.5rem; |
| border-radius: 16px; |
| box-shadow: 0 8px 32px 0 rgba(31, 38, 135, 0.2); |
| transition: all 0.3s ease; |
| } |
| |
| .usage-section:hover { |
| background: rgba(255, 255, 255, 0.08); |
| transform: translateY(-2px); |
| box-shadow: 0 12px 40px 0 rgba(31, 38, 135, 0.3); |
| } |
| |
| .usage-section h4 { |
| margin-bottom: 1rem; |
| color: rgba(255, 255, 255, 0.9); |
| font-size: 1.1rem; |
| font-weight: 600; |
| display: flex; |
| align-items: center; |
| gap: 0.5rem; |
| } |
| |
| .usage-section h4 i { |
| color: rgba(133, 48, 48, 0.8); |
| } |
| |
| .endpoint-list, .ip-list { |
| display: flex; |
| flex-direction: column; |
| gap: 0.5rem; |
| } |
| |
| .endpoint-item, .ip-item { |
| display: flex; |
| justify-content: space-between; |
| align-items: center; |
| padding: 0.75rem; |
| background: rgba(255, 255, 255, 0.08); |
| backdrop-filter: blur(5px); |
| border-radius: 8px; |
| border: 1px solid rgba(255, 255, 255, 0.1); |
| transition: all 0.3s ease; |
| } |
| |
| .endpoint-item:hover, .ip-item:hover { |
| background: rgba(255, 255, 255, 0.12); |
| transform: translateX(4px); |
| } |
| |
| .endpoint-name, .ip-address { |
| font-family: 'Courier New', monospace; |
| font-weight: 500; |
| color: rgba(255, 255, 255, 0.8); |
| font-size: 0.9rem; |
| } |
| |
| .endpoint-count, .ip-count { |
| color: rgba(133, 48, 48, 0.9); |
| font-weight: 600; |
| background: rgba(133, 48, 48, 0.1); |
| padding: 0.25rem 0.5rem; |
| border-radius: 12px; |
| font-size: 0.8rem; |
| } |
| |
| .ip-time { |
| font-size: 0.75rem; |
| color: rgba(255, 255, 255, 0.6); |
| font-style: italic; |
| } |
| |
| .daily-usage { |
| display: flex; |
| flex-direction: column; |
| gap: 0.75rem; |
| } |
| |
| .usage-day { |
| display: grid; |
| grid-template-columns: 70px 1fr 50px; |
| align-items: center; |
| gap: 1rem; |
| padding: 0.5rem; |
| border-radius: 8px; |
| transition: all 0.3s ease; |
| } |
| |
| .usage-day:hover { |
| background: rgba(255, 255, 255, 0.05); |
| } |
| |
| .usage-date { |
| font-size: 0.85rem; |
| font-weight: 500; |
| color: rgba(255, 255, 255, 0.8); |
| } |
| |
| .usage-bar-container { |
| background: rgba(255, 255, 255, 0.1); |
| border-radius: 10px; |
| height: 8px; |
| overflow: hidden; |
| position: relative; |
| } |
| |
| .usage-bar { |
| height: 100%; |
| background: linear-gradient(90deg, rgba(133, 48, 48, 0.8), rgba(166, 69, 69, 0.9)); |
| border-radius: 10px; |
| transition: width 0.6s ease; |
| position: relative; |
| } |
| |
| .usage-bar::after { |
| content: ''; |
| position: absolute; |
| top: 0; |
| left: 0; |
| right: 0; |
| bottom: 0; |
| background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.3), transparent); |
| animation: shimmer 2s infinite; |
| } |
| |
| @keyframes shimmer { |
| 0% { transform: translateX(-100%); } |
| 100% { transform: translateX(100%); } |
| } |
| |
| .usage-count { |
| font-size: 0.85rem; |
| font-weight: 600; |
| color: rgba(133, 48, 48, 0.9); |
| text-align: center; |
| } |
| |
| .no-data { |
| text-align: center; |
| padding: 2rem; |
| color: rgba(255, 255, 255, 0.5); |
| font-style: italic; |
| } |
| |
| .no-data-state, .error-state { |
| text-align: center; |
| padding: 3rem 2rem; |
| color: rgba(255, 255, 255, 0.6); |
| } |
| |
| .error-state i { |
| color: #ff6b6b; |
| font-size: 2.5rem; |
| margin-bottom: 1rem; |
| } |
| |
| .search-container { |
| margin-bottom: 2rem; |
| position: relative; |
| } |
| |
| .search-input { |
| width: 100%; |
| padding: 1rem 1rem 1rem 3rem; |
| border: 1px solid rgba(255, 255, 255, 0.2); |
| border-radius: 16px; |
| background: rgba(255, 255, 255, 0.05); |
| backdrop-filter: blur(10px); |
| font-size: 1rem; |
| transition: all 0.3s ease; |
| color: rgba(255, 255, 255, 0.9); |
| } |
| |
| .search-input::placeholder { |
| color: rgba(255, 255, 255, 0.5); |
| } |
| |
| .search-input:focus { |
| outline: none; |
| border-color: rgba(133, 48, 48, 0.8); |
| background: rgba(255, 255, 255, 0.08); |
| box-shadow: 0 0 0 3px rgba(133, 48, 48, 0.1); |
| } |
| |
| .search-icon { |
| position: absolute; |
| left: 1rem; |
| top: 50%; |
| transform: translateY(-50%); |
| color: rgba(133, 48, 48, 0.8); |
| font-size: 1.2rem; |
| } |
| |
| .plugin-card { |
| background: rgba(255, 255, 255, 0.05); |
| backdrop-filter: blur(10px); |
| -webkit-backdrop-filter: blur(10px); |
| border: 1px solid rgba(255, 255, 255, 0.1); |
| border-radius: 16px; |
| overflow: hidden; |
| transition: all 0.3s ease; |
| margin-bottom: 1rem; |
| } |
| |
| .plugin-card:hover { |
| background: rgba(255, 255, 255, 0.08); |
| transform: translateY(-2px); |
| box-shadow: 0 12px 40px 0 rgba(31, 38, 135, 0.3); |
| } |
| |
| .plugin-info { |
| margin-top: 0.5rem; |
| font-size: 0.85rem; |
| } |
| |
| .limit-info { |
| background: rgba(133, 48, 48, 0.1); |
| color: #853030; |
| padding: 0.25rem 0.5rem; |
| border-radius: 4px; |
| font-weight: 500; |
| } |
| |
| .user-item { |
| background: rgba(255, 255, 255, 0.05); |
| backdrop-filter: blur(10px); |
| -webkit-backdrop-filter: blur(10px); |
| border: 1px solid rgba(255, 255, 255, 0.1); |
| padding: 1.5rem; |
| border-radius: 16px; |
| margin-bottom: 1rem; |
| display: flex; |
| justify-content: space-between; |
| align-items: flex-start; |
| transition: all 0.3s ease; |
| } |
| |
| .user-item:hover { |
| background: rgba(255, 255, 255, 0.08); |
| transform: translateY(-2px); |
| box-shadow: 0 12px 40px 0 rgba(31, 38, 135, 0.3); |
| } |
| |
| .user-item.temp-banned { |
| border-left: 4px solid rgba(255, 193, 7, 0.8); |
| background: rgba(255, 193, 7, 0.05); |
| } |
| |
| .user-item.banned { |
| border-left: 4px solid rgba(220, 53, 69, 0.8); |
| background: rgba(220, 53, 69, 0.05); |
| } |
| |
| .user-info { |
| flex: 1; |
| } |
| |
| .user-name { |
| font-size: 1.2rem; |
| font-weight: 600; |
| color: rgba(255, 255, 255, 0.9); |
| margin-bottom: 0.5rem; |
| } |
| |
| .user-details { |
| display: flex; |
| flex-wrap: wrap; |
| gap: 0.75rem; |
| margin-bottom: 0.75rem; |
| } |
| |
| .user-email { |
| color: rgba(255, 255, 255, 0.7); |
| font-size: 0.9rem; |
| } |
| |
| .user-role { |
| background: rgba(255, 255, 255, 0.1); |
| backdrop-filter: blur(5px); |
| color: rgba(255, 255, 255, 0.8); |
| padding: 0.25rem 0.75rem; |
| border-radius: 12px; |
| font-size: 0.8rem; |
| font-weight: 500; |
| border: 1px solid rgba(255, 255, 255, 0.1); |
| } |
| |
| .premium-badge { |
| background: linear-gradient(45deg, rgba(255, 215, 0, 0.3), rgba(255, 237, 78, 0.3)); |
| backdrop-filter: blur(5px); |
| color: rgba(255, 215, 0, 1); |
| padding: 0.25rem 0.75rem; |
| border-radius: 12px; |
| font-size: 0.8rem; |
| font-weight: 600; |
| border: 1px solid rgba(255, 215, 0, 0.3); |
| box-shadow: 0 0 10px rgba(255, 215, 0, 0.2); |
| } |
| |
| .user-stats { |
| display: flex; |
| flex-wrap: wrap; |
| gap: 1rem; |
| font-size: 0.85rem; |
| color: rgba(255, 255, 255, 0.7); |
| margin-bottom: 0.75rem; |
| } |
| |
| .ban-info { |
| background: rgba(255, 193, 7, 0.1); |
| backdrop-filter: blur(5px); |
| border: 1px solid rgba(255, 193, 7, 0.3); |
| padding: 0.75rem; |
| border-radius: 8px; |
| font-size: 0.85rem; |
| color: rgba(255, 193, 7, 0.9); |
| margin-top: 0.5rem; |
| } |
| |
| .user-actions { |
| display: flex; |
| gap: 0.5rem; |
| flex-wrap: wrap; |
| } |
| |
| .pagination-controls { |
| display: flex; |
| justify-content: space-between; |
| align-items: center; |
| padding: 1rem; |
| margin-top: 1rem; |
| background: rgba(255, 255, 255, 0.05); |
| backdrop-filter: blur(10px); |
| border-radius: 12px; |
| border: 1px solid rgba(255, 255, 255, 0.1); |
| } |
| |
| .page-info { |
| color: rgba(255, 255, 255, 0.8); |
| font-weight: 500; |
| } |
| |
| .users-pagination-info { |
| color: rgba(255, 255, 255, 0.6); |
| font-size: 0.9rem; |
| margin-bottom: 1rem; |
| text-align: center; |
| padding: 0.5rem; |
| background: rgba(255, 255, 255, 0.05); |
| border-radius: 8px; |
| backdrop-filter: blur(5px); |
| } |
| |
| .btn { |
| padding: 0.5rem 1rem; |
| border: none; |
| border-radius: 8px; |
| font-weight: 500; |
| cursor: pointer; |
| transition: all 0.3s ease; |
| text-decoration: none; |
| display: inline-flex; |
| align-items: center; |
| gap: 0.5rem; |
| font-size: 0.9rem; |
| backdrop-filter: blur(10px); |
| border: 1px solid rgba(255, 255, 255, 0.1); |
| } |
| |
| .btn:disabled { |
| opacity: 0.5; |
| cursor: not-allowed; |
| transform: none !important; |
| } |
| |
| .btn-primary { |
| background: rgba(133, 48, 48, 0.8); |
| color: white; |
| border: 1px solid rgba(133, 48, 48, 0.3); |
| } |
| |
| .btn-primary:hover:not(:disabled) { |
| background: rgba(133, 48, 48, 1); |
| transform: translateY(-1px); |
| box-shadow: 0 4px 12px rgba(133, 48, 48, 0.3); |
| } |
| |
| .btn-secondary { |
| background: rgba(108, 117, 125, 0.8); |
| color: white; |
| border: 1px solid rgba(108, 117, 125, 0.3); |
| } |
| |
| .btn-secondary:hover:not(:disabled) { |
| background: rgba(108, 117, 125, 1); |
| transform: translateY(-1px); |
| } |
| |
| .btn-warning { |
| background: rgba(255, 193, 7, 0.8); |
| color: rgba(133, 100, 4, 1); |
| border: 1px solid rgba(255, 193, 7, 0.3); |
| } |
| |
| .btn-warning:hover:not(:disabled) { |
| background: rgba(255, 193, 7, 1); |
| transform: translateY(-1px); |
| box-shadow: 0 4px 12px rgba(255, 193, 7, 0.3); |
| } |
| |
| .btn-success { |
| background: rgba(40, 167, 69, 0.8); |
| color: white; |
| border: 1px solid rgba(40, 167, 69, 0.3); |
| } |
| |
| .btn-success:hover:not(:disabled) { |
| background: rgba(40, 167, 69, 1); |
| transform: translateY(-1px); |
| box-shadow: 0 4px 12px rgba(40, 167, 69, 0.3); |
| } |
| |
| .btn-danger { |
| background: rgba(220, 53, 69, 0.8); |
| color: white; |
| border: 1px solid rgba(220, 53, 69, 0.3); |
| } |
| |
| .btn-danger:hover:not(:disabled) { |
| background: rgba(220, 53, 69, 1); |
| transform: translateY(-1px); |
| box-shadow: 0 4px 12px rgba(220, 53, 69, 0.3); |
| } |
| |
| .no-users-state { |
| text-align: center; |
| padding: 3rem; |
| color: rgba(255, 255, 255, 0.6); |
| } |
| |
| .admin-card { |
| background: rgba(255, 255, 255, 0.05); |
| backdrop-filter: blur(10px); |
| -webkit-backdrop-filter: blur(10px); |
| border: 1px solid rgba(255, 255, 255, 0.1); |
| border-radius: 16px; |
| padding: 2rem; |
| margin-bottom: 2rem; |
| transition: all 0.3s ease; |
| } |
| |
| .admin-card:hover { |
| background: rgba(255, 255, 255, 0.08); |
| transform: translateY(-2px); |
| box-shadow: 0 12px 40px 0 rgba(31, 38, 135, 0.3); |
| } |
| |
| .admin-card h3 { |
| color: rgba(255, 255, 255, 0.9); |
| margin-bottom: 1.5rem; |
| display: flex; |
| align-items: center; |
| gap: 0.5rem; |
| } |
| |
| .admin-card h3 i { |
| color: rgba(133, 48, 48, 0.8); |
| } |
| |
| .stats-cards { |
| display: grid; |
| grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); |
| gap: 1.5rem; |
| margin-bottom: 2rem; |
| } |
| |
| .stat-card { |
| background: rgba(255, 255, 255, 0.05); |
| backdrop-filter: blur(10px); |
| -webkit-backdrop-filter: blur(10px); |
| border: 1px solid rgba(255, 255, 255, 0.1); |
| padding: 2rem; |
| border-radius: 16px; |
| display: flex; |
| align-items: center; |
| gap: 1rem; |
| transition: all 0.3s ease; |
| } |
| |
| .stat-card:hover { |
| background: rgba(255, 255, 255, 0.08); |
| transform: translateY(-3px); |
| box-shadow: 0 15px 50px 0 rgba(31, 38, 135, 0.4); |
| } |
| |
| .form-row { |
| display: grid; |
| grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); |
| gap: 1rem; |
| margin-bottom: 1.5rem; |
| } |
| |
| .form-group { |
| display: flex; |
| flex-direction: column; |
| } |
| |
| .form-group label { |
| color: rgba(255, 255, 255, 0.9); |
| margin-bottom: 0.5rem; |
| font-weight: 500; |
| font-size: 0.9rem; |
| } |
| |
| .form-group .required { |
| color: #ff6b6b; |
| margin-left: 0.25rem; |
| } |
| |
| .form-group input, |
| .form-group select { |
| padding: 0.75rem; |
| border: 1px solid rgba(255, 255, 255, 0.2); |
| border-radius: 8px; |
| background: rgba(255, 255, 255, 0.05); |
| color: rgba(255, 255, 255, 0.9); |
| font-size: 0.95rem; |
| transition: all 0.3s ease; |
| } |
| |
| .form-group input:focus, |
| .form-group select:focus { |
| outline: none; |
| border-color: rgba(133, 48, 48, 0.8); |
| background: rgba(255, 255, 255, 0.08); |
| box-shadow: 0 0 0 3px rgba(133, 48, 48, 0.1); |
| } |
| |
| .form-group input::placeholder { |
| color: rgba(255, 255, 255, 0.4); |
| } |
| |
| .form-group small { |
| color: rgba(255, 255, 255, 0.5); |
| font-size: 0.8rem; |
| margin-top: 0.25rem; |
| } |
| |
| @media (max-width: 768px) { |
| .countdown-time { |
| font-size: 2rem; |
| } |
| |
| .reset-timer-card { |
| padding: 1rem; |
| } |
| |
| .usage-overview { |
| grid-template-columns: 1fr; |
| } |
| |
| .usage-day { |
| grid-template-columns: 60px 1fr 40px; |
| gap: 0.5rem; |
| } |
| |
| .user-item { |
| flex-direction: column; |
| gap: 1rem; |
| } |
| |
| .user-actions { |
| width: 100%; |
| justify-content: flex-end; |
| } |
| |
| .pagination-controls { |
| flex-direction: column; |
| gap: 1rem; |
| } |
| |
| .dashboard-container { |
| flex-direction: column; |
| } |
| |
| .sidebar { |
| width: 100%; |
| position: static; |
| height: auto; |
| } |
| |
| .form-row { |
| grid-template-columns: 1fr; |
| } |
| |
| .stats-cards { |
| grid-template-columns: 1fr; |
| } |
| } |
| </style> |
| </head> |
| <body> |
| <nav class="navbar navbar-expand-lg navbar-dark"> |
| <div class="container"> |
| <a class="navbar-brand" href="/"> |
| <i class="fas fa-bolt"></i> DashX |
| </a> |
| <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav"> |
| <span class="navbar-toggler-icon"></span> |
| </button> |
| <div class="collapse navbar-collapse" id="navbarNav"> |
| <ul class="navbar-nav ms-auto"> |
| <li class="nav-item"> |
| <a class="nav-link" href="/profile" onclick="goToProfile()"> |
| <i class="fas fa-user"></i> Profile |
| </a> |
| </li> |
| <li class="nav-item"> |
| <a class="nav-link text-danger" href="#" onclick="logout()"> |
| <i class="fas fa-sign-out-alt"></i> Logout |
| </a> |
| </li> |
| </ul> |
| </div> |
| </div> |
| </nav> |
|
|
| <div class="dashboard-container"> |
| <div class="sidebar"> |
| <div class="sidebar-menu"> |
| <a href="#overview" class="menu-item active" onclick="showSection('overview')"> |
| <i class="fas fa-chart-line"></i> Overview |
| </a> |
| <a href="#api-stats" class="menu-item" onclick="showSection('api-stats')"> |
| <i class="fas fa-chart-area"></i> API Stats |
| </a> |
| <a href="#plugins" class="menu-item" onclick="showSection('plugins')"> |
| <i class="fas fa-plug"></i> API Plugins |
| </a> |
| <a href="#server-stats" class="menu-item" onclick="showSection('server-stats')"> |
| <i class="fas fa-server"></i> Server Stats |
| </a> |
| <a href="#events" class="menu-item" onclick="showSection('events')"> |
| <i class="fas fa-calendar"></i> Events |
| </a> |
| <a href="#settings" class="menu-item" onclick="showSection('settings')"> |
| <i class="fas fa-cog"></i> Settings |
| </a> |
| <div id="adminMenu" style="display: none;"> |
| <a href="#management" class="menu-item" onclick="showSection('management')"> |
| <i class="fas fa-users-cog"></i> Management |
| </a> |
| </div> |
| </div> |
| </div> |
|
|
| <div class="main-content"> |
| <div id="overview" class="section active"> |
| <h2><i class="fas fa-tachometer-alt"></i> Dashboard Overview</h2> |
| <div class="stats-cards"> |
| <div class="stat-card"> |
| <div class="stat-icon"> |
| <img src="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@6.4.0/svgs/solid/key.svg" alt="key" style="width: 3rem; height: 3rem; filter: invert(78%) sepia(45%) saturate(548%) hue-rotate(314deg) brightness(101%) contrast(101%);"> |
| </div> |
| <div class="stat-info"> |
| <div class="stat-number" id="userApiKey">Loading...</div> |
| <div class="stat-label">API Key</div> |
| </div> |
| </div> |
| <div class="stat-card"> |
| <div class="stat-icon"> |
| <img src="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@6.4.0/svgs/solid/chart-pie.svg" alt="chart" style="width: 3rem; height: 3rem; filter: invert(78%) sepia(45%) saturate(548%) hue-rotate(314deg) brightness(101%) contrast(101%);"> |
| </div> |
| <div class="stat-info"> |
| <div class="stat-number" id="userRequests">0</div> |
| <div class="stat-label">Total Requests</div> |
| </div> |
| </div> |
| <div class="stat-card"> |
| <div class="stat-icon"> |
| <img src="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@6.4.0/svgs/solid/cloud.svg" alt="cloud" style="width: 3rem; height: 3rem; filter: invert(78%) sepia(45%) saturate(548%) hue-rotate(314deg) brightness(101%) contrast(101%);"> |
| </div> |
| <div class="stat-info"> |
| <div class="stat-number" id="userRequestsToday">0</div> |
| <div class="stat-label">Today's Requests</div> |
| </div> |
| </div> |
| <div class="stat-card"> |
| <div class="stat-icon"> |
| <img src="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@6.4.0/svgs/solid/gauge-high.svg" alt="gauge" style="width: 3rem; height: 3rem; filter: invert(78%) sepia(45%) saturate(548%) hue-rotate(314deg) brightness(101%) contrast(101%);"> |
| </div> |
| <div class="stat-info"> |
| <div class="stat-number" id="userLimit">30</div> |
| <div class="stat-label">Daily Limit</div> |
| </div> |
| </div> |
| <div class="stat-card"> |
| <div class="stat-icon"> |
| <img src="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@6.4.0/svgs/solid/battery-three-quarters.svg" alt="battery" style="width: 3rem; height: 3rem; filter: invert(78%) sepia(45%) saturate(548%) hue-rotate(314deg) brightness(101%) contrast(101%);"> |
| </div> |
| <div class="stat-info"> |
| <div class="stat-number" id="userLimitToday">30</div> |
| <div class="stat-label">Remaining Limit (Personal)</div> |
| </div> |
| </div> |
| </div> |
|
|
| <div class="reset-timer-card glassmorphism"> |
| <div class="timer-header"> |
| <i class="fas fa-clock"></i> |
| <div> |
| <h3>Next Reset</h3> |
| <p>Daily limit resets at 00:00</p> |
| </div> |
| </div> |
|
|
| <div class="countdown-display"> |
| <div class="countdown-time"> |
| <span class="reset-countdown">00:00:00</span> |
| </div> |
| <div class="countdown-label"> |
| Hours : Minutes : Seconds |
| </div> |
| </div> |
|
|
| <div class="reset-progress-container"> |
| <div class="reset-progress"></div> |
| </div> |
|
|
| <div class="reset-info"> |
| <div> |
| <i class="fas fa-info-circle"></i> |
| <span>Your limit will be restored to maximum</span> |
| </div> |
| <div> |
| <i class="fas fa-sync-alt"></i> |
| </div> |
| </div> |
| </div> |
|
|
| <div class="usage-overview"> |
| <div class="usage-section"> |
| <h4><i class="fas fa-chart-bar"></i> API Usage Overview</h4> |
| <div class="endpoint-list"> |
| <div class="endpoint-item"> |
| <span class="endpoint-name">Loading...</span> |
| <span class="endpoint-count">0 requests</span> |
| </div> |
| </div> |
| </div> |
|
|
| |
|
|
| <div class="usage-section"> |
| <h4><i class="fas fa-calendar-alt"></i> Daily Usage (Last 7 Days)</h4> |
| <div class="daily-usage"> |
| <div class="usage-day"> |
| <span class="usage-date">Loading...</span> |
| <div class="usage-bar-container"> |
| <div class="usage-bar" style="width: 0%;"></div> |
| </div> |
| <span class="usage-count">0</span> |
| </div> |
| </div> |
| </div> |
|
|
| <div class="usage-section"> |
| <h4><i class="fas fa-network-wired"></i> Recent IP Addresses</h4> |
| <div class="ip-list"> |
| <div class="ip-item"> |
| <div> |
| <span class="ip-address">Loading...</span> |
| <div class="ip-time">Just now</div> |
| </div> |
| <span class="ip-count">0 requests</span> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
|
|
| <div id="plugins" class="section"> |
| <h2><i class="fas fa-plug"></i> Available API Plugins</h2> |
| <p style="margin-bottom: 2rem; opacity: 0.8;">Discover and test our API endpoints with interactive documentation</p> |
|
|
| <div class="search-container"> |
| <i class="fas fa-search search-icon"></i> |
| <input type="text" |
| class="search-input" |
| placeholder="Search plugins by name, description, or tags..." |
| oninput="searchPlugins(this.value)" |
| id="pluginSearch"> |
| </div> |
|
|
| <div class="plugins-grid" id="pluginsGrid"> |
| <div class="loading"> |
| <i class="fas fa-spinner fa-spin" style="margin-right: 0.5rem;"></i> |
| Loading plugins... |
| </div> |
| </div> |
| </div> |
|
|
| |
|
|
| <div id="server-stats" class="section"> |
| <h2><i class="fas fa-server"></i> Server Statistics</h2> |
|
|
| |
|
|
| <div class="stats-cards"> |
| <div class="stat-card"> |
| <div class="stat-icon"> |
| <img src="https://api.iconify.design/mdi/account-group.svg?color=%23ba68c8&width=48&height=48" alt="users"> |
| </div> |
| <div class="stat-info"> |
| <div class="stat-number" id="totalUsersCount">0</div> |
| <div class="stat-label">Total Users</div> |
| </div> |
| </div> |
| <div class="stat-card"> |
| <div class="stat-icon"> |
| <img src="https://api.iconify.design/mdi/account.svg?color=%23ce93d8&width=48&height=48" alt="user"> |
| </div> |
| <div class="stat-info"> |
| <div class="stat-number" id="regularUsersCount">0</div> |
| <div class="stat-label">Regular Users</div> |
| </div> |
| </div> |
| <div class="stat-card"> |
| <div class="stat-icon"> |
| <img src="https://api.iconify.design/mdi/crown.svg?color=%23ba68c8&width=48&height=48" alt="crown"> |
| </div> |
| <div class="stat-info"> |
| <div class="stat-number" id="premiumUsersCount">0</div> |
| <div class="stat-label">Premium Users</div> |
| </div> |
| </div> |
| </div> |
|
|
| <div class="admin-card"> |
| <h3><i class="fas fa-chart-pie"></i> User Role Distribution</h3> |
| <canvas id="roleChart" style="max-height: 300px;"></canvas> |
| </div> |
|
|
| <div class="admin-card"> |
| <h3><i class="fas fa-database"></i> Database Statistics</h3> |
| <div class="stats-grid" style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 1.5rem;"> |
| <div class="stat-item"> |
| <i class="fas fa-hdd" style="font-size: 2rem; color: rgba(133, 48, 48, 0.8); margin-bottom: 0.5rem;"></i> |
| <span class="stat-value" id="dbSize">0 MB</span> |
| <span class="stat-label">Database Size</span> |
| </div> |
| <div class="stat-item"> |
| <i class="fas fa-memory" style="font-size: 2rem; color: rgba(133, 48, 48, 0.8); margin-bottom: 0.5rem;"></i> |
| <span class="stat-value" id="ramUsage">0 MB</span> |
| <span class="stat-label">RAM Usage</span> |
| </div> |
| <div class="stat-item"> |
| <i class="fas fa-microchip" style="font-size: 2rem; color: rgba(133, 48, 48, 0.8); margin-bottom: 0.5rem;"></i> |
| <span class="stat-value" id="cpuUsage">0%</span> |
| <span class="stat-label">CPU Usage</span> |
| </div> |
| <div class="stat-item"> |
| <i class="fas fa-server" style="font-size: 2rem; color: rgba(133, 48, 48, 0.8); margin-bottom: 0.5rem;"></i> |
| <span class="stat-value" id="storageUsed">0 GB</span> |
| <span class="stat-label">Storage Used</span> |
| </div> |
| </div> |
| </div> |
|
|
| <div class="admin-card"> |
| <h3><i class="fas fa-chart-bar"></i> Role Distribution Details</h3> |
| <div class="stats-grid" style="display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 1rem;"> |
| <div class="stat-item"> |
| <span class="stat-value" id="cheapCount">0</span> |
| <span class="stat-label">Cheap Role</span> |
| </div> |
| <div class="stat-item"> |
| <span class="stat-value" id="premiumCount">0</span> |
| <span class="stat-label">Premium Role</span> |
| </div> |
| <div class="stat-item"> |
| <span class="stat-value" id="vipCount">0</span> |
| <span class="stat-label">VIP Role</span> |
| </div> |
| <div class="stat-item"> |
| <span class="stat-value" id="supremeCount">0</span> |
| <span class="stat-label">Supreme Role</span> |
| </div> |
| </div> |
| </div> |
| </div> |
|
|
| <div id="api-stats" class="section"> |
| <h2><i class="fas fa-chart-area"></i> API Statistics</h2> |
| <p style="margin-bottom: 2rem; opacity: 0.8;">Global API usage statistics and analytics</p> |
|
|
| <div class="stats-cards"> |
| <div class="stat-card"> |
| <div class="stat-icon"> |
| <i class="fas fa-globe"></i> |
| </div> |
| <div class="stat-info"> |
| <div class="stat-number" id="globalTotalRequests">0</div> |
| <div class="stat-label">Total Requests (All Users)</div> |
| </div> |
| </div> |
| <div class="stat-card"> |
| <div class="stat-icon"> |
| <i class="fas fa-calendar-day"></i> |
| </div> |
| <div class="stat-info"> |
| <div class="stat-number" id="globalTodayRequests">0</div> |
| <div class="stat-label">Today's Requests (All Users)</div> |
| </div> |
| </div> |
| <div class="stat-card"> |
| <div class="stat-icon"> |
| <i class="fas fa-check-circle"></i> |
| </div> |
| <div class="stat-info"> |
| <div class="stat-number" id="successRate">0%</div> |
| <div class="stat-label">Success Rate</div> |
| </div> |
| </div> |
| <div class="stat-card"> |
| <div class="stat-icon"> |
| <i class="fas fa-times-circle"></i> |
| </div> |
| <div class="stat-info"> |
| <div class="stat-number" id="failRate">0%</div> |
| <div class="stat-label">Fail Rate</div> |
| </div> |
| </div> |
| </div> |
|
|
| <div class="charts-grid" style="display: grid; grid-template-columns: repeat(auto-fit, minmax(400px, 1fr)); gap: 2rem; margin-top: 2rem;"> |
| <div class="admin-card"> |
| <h3><i class="fas fa-chart-pie"></i> Top Endpoints Distribution</h3> |
| <canvas id="topEndpointsChart" style="max-height: 350px;"></canvas> |
| </div> |
|
|
| <div class="admin-card"> |
| <h3><i class="fas fa-percentage"></i> Success vs Fail Rate</h3> |
| <canvas id="successFailChart" style="max-height: 350px;"></canvas> |
| </div> |
| </div> |
|
|
| <div class="admin-card" style="margin-top: 2rem;"> |
| <h3><i class="fas fa-chart-bar"></i> Daily Request Statistics (Last 7 Days)</h3> |
| <canvas id="dailyRequestsChart" style="max-height: 400px;"></canvas> |
| </div> |
|
|
| <div class="admin-card" style="margin-top: 2rem;"> |
| <h3><i class="fas fa-chart-line"></i> Hourly Trends (Last 24 Hours)</h3> |
| <canvas id="hourlyTrendsChart" style="max-height: 400px;"></canvas> |
| </div> |
|
|
| <div class="admin-card" style="margin-top: 2rem;"> |
| <h3><i class="fas fa-list-ol"></i> Top 10 Most Used Endpoints</h3> |
| <div id="topEndpointsList"> |
| <div class="loading"> |
| <i class="fas fa-spinner fa-spin"></i> Loading... |
| </div> |
| </div> |
| </div> |
| </div> |
|
|
| <div id="events" class="section"> |
| <h2><i class="fas fa-calendar"></i> Events & Rewards</h2> |
| <div class="events-container"> |
| <div class="redeem-section"> |
| <h3><i class="fas fa-gift"></i> Redeem Code</h3> |
| <p style="margin-bottom: 1.5rem; opacity: 0.8;">Enter a redeem code to unlock premium features or additional limits</p> |
| <div class="form-group"> |
| <input type="text" id="redeemCode" placeholder="Enter your redeem code" style="text-transform: uppercase;"> |
| <button onclick="redeemCode()" class="btn btn-primary"> |
| <i class="fas fa-magic"></i> Redeem |
| </button> |
| </div> |
| </div> |
| </div> |
| </div> |
|
|
| <div id="settings" class="section"> |
| <h2><i class="fas fa-cog"></i> Settings</h2> |
| <div class="settings-container"> |
| <div class="setting-card"> |
| <h3><i class="fas fa-user-edit"></i> Profile Settings</h3> |
| <div class="form-group"> |
| <label>Username</label> |
| <input type="text" id="usernameInput" placeholder="Enter new username"> |
| </div> |
| <button onclick="updateProfile()" class="btn btn-primary"> |
| <i class="fas fa-save"></i> Update Profile |
| </button> |
| </div> |
|
|
| <div class="setting-card" id="premiumSettings" style="display: none;"> |
| <h3><i class="fas fa-crown"></i> Premium Features</h3> |
| <button onclick="regenerateApiKey()" class="btn btn-warning"> |
| <i class="fas fa-sync"></i> Regenerate API Key |
| </button> |
| <p class="text-muted">Generate a new API key (Premium only)</p> |
| </div> |
|
|
| <div class="setting-card danger-zone"> |
| <h3><i class="fas fa-exclamation-triangle"></i> Danger Zone</h3> |
| <button onclick="deleteAccount()" class="btn btn-danger"> |
| <i class="fas fa-trash"></i> Delete Account |
| </button> |
| <p class="text-muted">This action cannot be undone</p> |
| </div> |
| </div> |
| </div> |
|
|
| <div id="management" class="section"> |
| <h2><i class="fas fa-users-cog"></i> Admin Management</h2> |
| <div class="admin-container"> |
| <div class="admin-card"> |
| <h3><i class="fas fa-users"></i> User Management</h3> |
| <div id="adminUsersList"> |
| <div class="loading"> |
| <i class="fas fa-spinner fa-spin"></i> Loading users... |
| </div> |
| </div> |
| </div> |
|
|
| <div class="admin-card"> |
| <h3><i class="fas fa-user-tag"></i> Set User Role</h3> |
| <div class="form-row"> |
| <div class="form-group" style="grid-column: 1 / -1;"> |
| <label>Search User <span class="required">*</span></label> |
| <input type="text" id="searchUserInput" placeholder="Search by username or email" oninput="searchUsersForRole(this.value)"> |
| <div id="userSearchResults" style="display: none; margin-top: 0.5rem; background: rgba(255,255,255,0.05); border-radius: 8px; max-height: 200px; overflow-y: auto;"></div> |
| </div> |
| <div class="form-group"> |
| <label>Selected User</label> |
| <input type="text" id="selectedUserDisplay" placeholder="No user selected" readonly> |
| <input type="hidden" id="selectedUserId"> |
| </div> |
| <div class="form-group"> |
| <label>Role <span class="required">*</span></label> |
| <select id="assignRoleType"> |
| <option value="cheap">Cheap (Limit 500)</option> |
| <option value="premium">Premium (Limit 1500)</option> |
| <option value="vip">VIP (Limit 2500)</option> |
| <option value="supreme">Supreme (Limit 3000)</option> |
| </select> |
| </div> |
| <div class="form-group"> |
| <label>Custom API Key <span style="color: #666; font-size: 0.85em;">(Optional)</span></label> |
| <input type="text" id="customApiKey" placeholder="Leave empty for current key"> |
| <small>All roles support custom API keys</small> |
| </div> |
| </div> |
| <button onclick="assignUserRole()" class="btn btn-primary"> |
| <i class="fas fa-user-check"></i> Assign Role |
| </button> |
| </div> |
|
|
| <div class="admin-card"> |
| <h3><i class="fas fa-ticket-alt"></i> Create Redeem Code</h3> |
| <div class="form-row"> |
| <div class="form-group"> |
| <label>Type <span class="required">*</span></label> |
| <select id="redeemType"> |
| <option value="limit">Limit Only</option> |
| <option value="premium">Premium Only</option> |
| <option value="both">Both</option> |
| </select> |
| </div> |
| <div class="form-group" id="limitContainer" style="display: none;"> |
| <label>Limit Value</label> |
| <input type="number" id="limitValue" min="0" placeholder="Additional limit"> |
| <small>Optional for Premium Only</small> |
| </div> |
| <div class="form-group" id="codeExpiredContainer" style="display: none;"> |
| <label>Code Expired <span class="required">*</span></label> |
| <input type="datetime-local" id="codeExpired" required> |
| <small>When the code expires</small> |
| </div> |
| <div class="form-group" id="premiumExpiredContainer" style="display: none;"> |
| <label>Premium Expired <span class="required">*</span></label> |
| <input type="datetime-local" id="premiumExpired"> |
| <small>When premium access expires</small> |
| </div> |
| </div> |
| <button onclick="createRedeemCode()" class="btn btn-primary"> |
| <i class="fas fa-plus"></i> Create Code |
| </button> |
| </div> |
|
|
| <div class="admin-card"> |
| <h3><i class="fas fa-chart-pie"></i> System Statistics</h3> |
| <div class="stats-grid"> |
| <div class="stat-item"> |
| <span class="stat-value" id="adminTotalUsers">0</span> |
| <span class="stat-label">Total Users</span> |
| </div> |
| <div class="stat-item"> |
| <span class="stat-value" id="adminTotalRequests">0</span> |
| <span class="stat-label">Total Requests</span> |
| </div> |
| <div class="stat-item"> |
| <span class="stat-value" id="adminTodayRequests">0</span> |
| <span class="stat-label">Today's Requests</span> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
|
|
| <script> |
| (function(){ |
| function detectDevTools(){ |
| const threshold = 160; |
| const widthThreshold = window.outerWidth - window.innerWidth > threshold; |
| const heightThreshold = window.outerHeight - window.innerHeight > threshold; |
| if(widthThreshold || heightThreshold) window.location.href = "/denied"; |
| } |
| |
| document.addEventListener("contextmenu", e => e.preventDefault()); |
| document.onkeydown = function(e){ |
| if(e.keyCode === 123 || (e.ctrlKey && e.shiftKey && ['I','C','J'].includes(e.key?.toUpperCase())) || (e.ctrlKey && e.key?.toUpperCase() === 'U')){ |
| e.preventDefault(); |
| window.location.href = "/denied"; |
| } |
| }; |
| |
| setInterval(() => { |
| if(window.eruda) window.location.href = "/denied"; |
| detectDevTools(); |
| try{ |
| console.profile(); |
| console.profileEnd(); |
| }catch(e){} |
| try{ |
| if(console.clear.toString().length > 100) window.location.href = "/denied"; |
| }catch(e){} |
| }, 1000); |
| })(); |
| </script> |
|
|
| <script src="https://cdnjs.cloudflare.com/ajax/libs/sweetalert2/11.10.8/sweetalert2.min.js"></script> |
| <script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.0/js/bootstrap.bundle.min.js"></script> |
| <script src="dashboard.js"></script> |
| </body> |
| </html> |