Spaces:
Running
Running
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Analytics Dashboard</title> | |
| <script src="https://cdn.jsdelivr.net/npm/chart.js"></script> | |
| <script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script> | |
| <style> | |
| :root { | |
| --primary-color: #4361ee; | |
| --primary-hover: #3a56d4; | |
| --secondary-color: #3f37c9; | |
| --accent-color: #4cc9f0; | |
| --success-color: #4bb543; | |
| --warning-color: #f8961e; | |
| --danger-color: #f94144; | |
| --light-color: #f8f9fa; | |
| --dark-color: #212529; | |
| --border-color: #dee2e6; | |
| --shadow: 0 4px 6px rgba(0, 0, 0, 0.1); | |
| --shadow-lg: 0 10px 15px rgba(0, 0, 0, 0.1); | |
| } | |
| * { | |
| margin: 0; | |
| padding: 0; | |
| box-sizing: border-box; | |
| font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; | |
| } | |
| body { | |
| background-color: #f5f7fa; | |
| color: var(--dark-color); | |
| line-height: 1.6; | |
| } | |
| .dashboard { | |
| display: grid; | |
| grid-template-columns: 250px 1fr; | |
| min-height: 100vh; | |
| } | |
| /* Sidebar */ | |
| .sidebar { | |
| background-color: white; | |
| box-shadow: var(--shadow); | |
| padding: 1.5rem; | |
| position: sticky; | |
| top: 0; | |
| height: 100vh; | |
| overflow-y: auto; | |
| } | |
| .sidebar-header { | |
| display: flex; | |
| align-items: center; | |
| margin-bottom: 2rem; | |
| padding-bottom: 1rem; | |
| border-bottom: 1px solid var(--border-color); | |
| } | |
| .sidebar-header h2 { | |
| font-size: 1.2rem; | |
| font-weight: 600; | |
| margin-left: 0.5rem; | |
| } | |
| .sidebar-menu { | |
| list-style: none; | |
| } | |
| .sidebar-menu li { | |
| margin-bottom: 0.5rem; | |
| } | |
| .sidebar-menu a { | |
| display: flex; | |
| align-items: center; | |
| padding: 0.75rem 1rem; | |
| color: var(--dark-color); | |
| text-decoration: none; | |
| border-radius: 0.5rem; | |
| transition: all 0.3s ease; | |
| } | |
| .sidebar-menu a:hover, .sidebar-menu a.active { | |
| background-color: var(--primary-color); | |
| color: white; | |
| } | |
| .sidebar-menu i { | |
| margin-right: 0.75rem; | |
| width: 18px; | |
| } | |
| /* Main Content */ | |
| .main-content { | |
| padding: 1.5rem; | |
| } | |
| .header { | |
| display: flex; | |
| justify-content: space-between; | |
| align-items: center; | |
| margin-bottom: 1.5rem; | |
| } | |
| .header h1 { | |
| font-size: 1.5rem; | |
| font-weight: 600; | |
| } | |
| .header-actions { | |
| display: flex; | |
| align-items: center; | |
| gap: 1rem; | |
| } | |
| .btn { | |
| padding: 0.5rem 1rem; | |
| border: none; | |
| border-radius: 0.5rem; | |
| cursor: pointer; | |
| font-weight: 500; | |
| transition: all 0.3s ease; | |
| } | |
| .btn-primary { | |
| background-color: var(--primary-color); | |
| color: white; | |
| } | |
| .btn-primary:hover { | |
| background-color: var(--primary-hover); | |
| } | |
| .btn-secondary { | |
| background-color: var(--light-color); | |
| color: var(--dark-color); | |
| } | |
| .btn-secondary:hover { | |
| background-color: var(--border-color); | |
| } | |
| /* Cards */ | |
| .cards { | |
| display: grid; | |
| grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); | |
| gap: 1.5rem; | |
| margin-bottom: 1.5rem; | |
| } | |
| .card { | |
| background-color: white; | |
| border-radius: 0.75rem; | |
| padding: 1.5rem; | |
| box-shadow: var(--shadow); | |
| transition: transform 0.3s ease, box-shadow 0.3s ease; | |
| } | |
| .card:hover { | |
| transform: translateY(-5px); | |
| box-shadow: var(--shadow-lg); | |
| } | |
| .card-header { | |
| display: flex; | |
| justify-content: space-between; | |
| align-items: center; | |
| margin-bottom: 1rem; | |
| } | |
| .card-title { | |
| font-size: 0.9rem; | |
| color: #6c757d; | |
| text-transform: uppercase; | |
| font-weight: 600; | |
| letter-spacing: 0.5px; | |
| } | |
| .card-value { | |
| font-size: 2rem; | |
| font-weight: 700; | |
| margin-bottom: 0.5rem; | |
| } | |
| .card-change { | |
| display: flex; | |
| align-items: center; | |
| font-size: 0.875rem; | |
| } | |
| .card-change.positive { | |
| color: var(--success-color); | |
| } | |
| .card-change.negative { | |
| color: var(--danger-color); | |
| } | |
| .card-change i { | |
| margin-right: 0.25rem; | |
| } | |
| /* Charts */ | |
| .charts { | |
| display: grid; | |
| grid-template-columns: repeat(auto-fit, minmax(400px, 1fr)); | |
| gap: 1.5rem; | |
| margin-bottom: 1.5rem; | |
| } | |
| .chart-container { | |
| background-color: white; | |
| border-radius: 0.75rem; | |
| padding: 1.5rem; | |
| box-shadow: var(--shadow); | |
| } | |
| .chart-header { | |
| display: flex; | |
| justify-content: space-between; | |
| align-items: center; | |
| margin-bottom: 1.5rem; | |
| } | |
| .chart-title { | |
| font-size: 1.1rem; | |
| font-weight: 600; | |
| } | |
| .chart-selector { | |
| display: flex; | |
| gap: 0.5rem; | |
| } | |
| .chart-selector button { | |
| padding: 0.25rem 0.75rem; | |
| border: 1px solid var(--border-color); | |
| background-color: white; | |
| border-radius: 0.5rem; | |
| cursor: pointer; | |
| font-size: 0.875rem; | |
| } | |
| .chart-selector button.active { | |
| background-color: var(--primary-color); | |
| color: white; | |
| border-color: var(--primary-color); | |
| } | |
| /* Tables */ | |
| .table-container { | |
| background-color: white; | |
| border-radius: 0.75rem; | |
| padding: 1.5rem; | |
| box-shadow: var(--shadow); | |
| overflow-x: auto; | |
| } | |
| .table { | |
| width: 100%; | |
| border-collapse: collapse; | |
| } | |
| .table thead { | |
| background-color: var(--light-color); | |
| } | |
| .table th, .table td { | |
| padding: 1rem; | |
| text-align: left; | |
| border-bottom: 1px solid var(--border-color); | |
| } | |
| .table th { | |
| font-weight: 600; | |
| color: var(--dark-color); | |
| } | |
| .table tr:hover { | |
| background-color: var(--light-color); | |
| } | |
| /* Responsive */ | |
| @media (max-width: 768px) { | |
| .dashboard { | |
| grid-template-columns: 1fr; | |
| } | |
| .sidebar { | |
| position: fixed; | |
| top: 0; | |
| left: -100%; | |
| width: 250px; | |
| height: 100vh; | |
| z-index: 1000; | |
| transition: left 0.3s ease; | |
| } | |
| .sidebar.active { | |
| left: 0; | |
| } | |
| .main-content { | |
| padding: 1rem; | |
| } | |
| .header { | |
| flex-direction: column; | |
| align-items: flex-start; | |
| gap: 1rem; | |
| } | |
| .header-actions { | |
| width: 100%; | |
| justify-content: space-between; | |
| } | |
| .cards { | |
| grid-template-columns: 1fr; | |
| } | |
| .charts { | |
| grid-template-columns: 1fr; | |
| } | |
| } | |
| /* Built with anycoder */ | |
| .anycoder-link { | |
| position: fixed; | |
| bottom: 1rem; | |
| right: 1rem; | |
| background-color: var(--primary-color); | |
| color: white; | |
| padding: 0.5rem 1rem; | |
| border-radius: 0.5rem; | |
| text-decoration: none; | |
| font-size: 0.875rem; | |
| box-shadow: var(--shadow); | |
| z-index: 100; | |
| } | |
| .anycoder-link:hover { | |
| background-color: var(--primary-hover); | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="dashboard"> | |
| <!-- Sidebar --> | |
| <aside class="sidebar"> | |
| <div class="sidebar-header"> | |
| <i data-feather="bar-chart-2"></i> | |
| <h2>Analytics</h2> | |
| </div> | |
| <ul class="sidebar-menu"> | |
| <li><a href="#" class="active"><i data-feather="home"></i>Dashboard</a></li> | |
| <li><a href="#"><i data-feather="trending-up"></i>Overview</a></li> | |
| <li><a href="#"><i data-feather="activity"></i>Reports</a></li> | |
| <li><a href="#"><i data-feather="users"></i>Users</a></li> | |
| <li><a href="#"><i data-feather="settings"></i>Settings</a></li> | |
| </ul> | |
| </aside> | |
| <!-- Main Content --> | |
| <main class="main-content"> | |
| <header class="header"> | |
| <h1>Analytics Dashboard</h1> | |
| <div class="header-actions"> | |
| <button class="btn btn-secondary">Export</button> | |
| <button class="btn btn-primary">Generate Report</button> | |
| </div> | |
| </header> | |
| <!-- Cards --> | |
| <div class="cards"> | |
| <div class="card"> | |
| <div class="card-header"> | |
| <span class="card-title">Total Revenue</span> | |
| <i data-feather="dollar-sign" style="color: var(--primary-color);"></i> | |
| </div> | |
| <div class="card-value">$124,567</div> | |
| <div class="card-change positive"> | |
| <i data-feather="trending-up"></i> | |
| <span>12.5% vs last month</span> | |
| </div> | |
| </div> | |
| <div class="card"> | |
| <div class="card-header"> | |
| <span class="card-title">Active Users</span> | |
| <i data-feather="users" style="color: var(--success-color);"></i> | |
| </div> | |
| <div class="card-value">1,245</div> | |
| <div class="card-change positive"> | |
| <i data-feather="trending-up"></i> | |
| <span>8.2% vs last month</span> | |
| </div> | |
| </div> | |
| <div class="card"> | |
| <div class="card-header"> | |
| <span class="card-title">Conversion Rate</span> | |
| <i data-feather="percent" style="color: var(--warning-color);"></i> | |
| </div> | |
| <div class="card-value">3.2%</div> | |
| <div class="card-change negative"> | |
| <i data-feather="trending-down"></i> | |
| <span>1.8% vs last month</span> | |
| </div> | |
| </div> | |
| <div class="card"> | |
| <div class="card-header"> | |
| <span class="card-title">Bounce Rate</span> | |
| <i data-feather="arrow-down-circle" style="color: var(--danger-color);"></i> | |
| </div> | |
| <div class="card-value">24.5%</div> | |
| <div class="card-change negative"> | |
| <i data-feather="trending-down"></i> | |
| <span>3.1% vs last month</span> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Charts --> | |
| <div class="charts"> | |
| <div class="chart-container"> | |
| <div class="chart-header"> | |
| <h3 class="chart-title">Revenue Overview</h3> | |
| <div class="chart-selector"> | |
| <button class="active" data-chart="monthly">Monthly</button> | |
| <button data-chart="quarterly">Quarterly</button> | |
| <button data-chart="yearly">Yearly</button> | |
| </div> | |
| </div> | |
| <canvas id="revenueChart"></canvas> | |
| </div> | |
| <div class="chart-container"> | |
| <div class="chart-header"> | |
| <h3 class="chart-title">User Activity</h3> | |
| <div class="chart-selector"> | |
| <button class="active" data-chart="weekly">Weekly</button> | |
| <button data-chart="monthly">Monthly</button> | |
| </div> | |
| </div> | |
| <canvas id="activityChart"></canvas> | |
| </div> | |
| </div> | |
| <!-- Data Table --> | |
| <div class="table-container"> | |
| <h3 class="chart-title" style="margin-bottom: 1.5rem;">Recent Transactions</h3> | |
| <table class="table"> | |
| <thead> | |
| <tr> | |
| <th>ID</th> | |
| <th>Customer</th> | |
| <th>Amount</th> | |
| <th>Status</th> | |
| <th>Date</th> | |
| </tr> | |
| </thead> | |
| <tbody id="transactionsTable"> | |
| <!-- Table content will be generated by JavaScript --> | |
| </tbody> | |
| </table> | |
| </div> | |
| </main> | |
| </div> | |
| <!-- Built with anycoder link --> | |
| <a href="https://huggingface.co/spaces/akhaliq/anycoder" class="anycoder-link" target="_blank"> | |
| Built with anycoder | |
| </a> | |
| <script> | |
| // Initialize Feather Icons | |
| feather.replace(); | |
| // Chart.js configuration | |
| const chartColors = { | |
| primary: '#4361ee', | |
| secondary: '#3f37c9', | |
| accent: '#4cc9f0', | |
| success: '#4bb543', | |
| warning: '#f8961e', | |
| danger: '#f94144' | |
| }; | |
| // Revenue Chart | |
| const revenueCtx = document.getElementById('revenueChart').getContext('2d'); | |
| const revenueChart = new Chart(revenueCtx, { | |
| type: 'line', | |
| data: { | |
| labels: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], | |
| datasets: [{ | |
| label: 'Revenue', | |
| data: [12000, 15000, 18000, 22000, 25000, 28000, 32000, 35000, 38000, 42000, 45000, 48000], | |
| backgroundColor: 'rgba(67, 97, 238, 0.1)', | |
| borderColor: chartColors.primary, | |
| borderWidth: 2, | |
| tension: 0.4, | |
| fill: true | |
| }] | |
| }, | |
| options: { | |
| responsive: true, | |
| maintainAspectRatio: true, | |
| plugins: { | |
| legend: { | |
| display: false | |
| } | |
| }, | |
| scales: { | |
| y: { | |
| beginAtZero: true, | |
| ticks: { | |
| callback: function(value) { | |
| return '$' + value.toLocaleString(); | |
| } | |
| } | |
| } | |
| } | |
| } | |
| }); | |
| // Activity Chart | |
| const activityCtx = document.getElementById('activityChart').getContext('2d'); | |
| const activityChart = new Chart(activityCtx, { | |
| type: 'bar', | |
| data: { | |
| labels: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'], | |
| datasets: [{ | |
| label: 'Active Users', | |
| data: [120, 190, 150, 220, 180, 250, 200], | |
| backgroundColor: chartColors.success, | |
| borderRadius: 5 | |
| }, { | |
| label: 'New Users', | |
| data: [30, 45, 35, 50, 40, 60, 50], | |
| backgroundColor: chartColors.accent, | |
| borderRadius: 5 | |
| }] | |
| }, | |
| options: { | |
| responsive: true, | |
| maintainAspectRatio: true, | |
| plugins: { | |
| legend: { | |
| position: 'top', | |
| align: 'end' | |
| } | |
| }, | |
| scales: { | |
| y: { | |
| beginAtZero: true | |
| } | |
| } | |
| } | |
| }); | |
| // Chart selector functionality | |
| document.querySelectorAll('.chart-selector button').forEach(button => { | |
| button.addEventListener('click', function() { | |
| // Remove active class from all buttons in the same selector | |
| this.parentElement.querySelectorAll('button').forEach(btn => { | |
| btn.classList.remove('active'); | |
| }); | |
| // Add active class to clicked button | |
| this.classList.add('active'); | |
| // Update chart data based on selection | |
| const chartType = this.dataset.chart; | |
| if (this.closest('.chart-container').querySelector('#revenueChart')) { | |
| updateRevenueChart(chartType); | |
| } else if (this.closest('.chart-container').querySelector('#activityChart')) { | |
| updateActivityChart(chartType); | |
| } | |
| }); | |
| }); | |
| function updateRevenueChart(period) { | |
| let labels = []; | |
| let data = []; | |
| switch(period) { | |
| case 'monthly': | |
| labels = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']; | |
| data = [12000, 15000, 18000, 22000, 25000, 28000, 32000, 35000, 38000, 42000, 45000, 48000]; | |
| break; | |
| case 'quarterly': | |
| labels = ['Q1', 'Q2', 'Q3', 'Q4']; | |
| data = [45000, 85000, 115000, 135000]; | |
| break; | |
| case 'yearly': | |
| labels = ['2020', '2021', '2022', '2023']; | |
| data = [300000, 450000, 600000, 750000]; | |
| break; | |
| } | |
| revenueChart.data.labels = labels; | |
| revenueChart.data.datasets[0].data = data; | |
| revenueChart.update(); | |
| } | |
| function updateActivityChart(period) { | |
| let labels = []; | |
| let activeUsers = []; | |
| let newUsers = []; | |
| switch(period) { | |
| case 'weekly': | |
| labels = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']; | |
| activeUsers = [120, 190, 150, 220, 180, 250, 200]; | |
| newUsers = [30, 45, 35, 50, 40, 60, 50]; | |
| break; | |
| case 'monthly': | |
| labels = ['Week 1', 'Week 2', 'Week 3', 'Week 4']; | |
| activeUsers = [800, 950, 1100, 1200]; | |
| newUsers = [150, 180, 200, 220]; | |
| break; | |
| } | |
| activityChart.data.labels = labels; | |
| activityChart.data.datasets[0].data = activeUsers; | |
| activityChart.data.datasets[1].data = newUsers; | |
| activityChart.update(); | |
| } | |
| // Generate table data | |
| function generateTransactions() { | |
| const transactions = [ | |
| { id: '#1001', customer: 'John Doe', amount: 125.50, status: 'completed', date: '2023-05-15' }, | |
| { id: '#1002', customer: 'Jane Smith', amount: 89.99, status: 'pending', date: '2023-05-14' }, | |
| { id: '#1003', customer: 'Robert Johnson', amount: 245.75, status: 'completed', date: '2023-05-13' }, | |
| { id: '#1004', customer: 'Emily Davis', amount: 67.20, status: 'failed', date: '2023-05-12' }, | |
| { id: '#1005', customer: 'Michael Brown', amount: 180.00, status: 'completed', date: '2023-05-11' }, | |
| { id: '#1006', customer: 'Sarah Wilson', amount: 95.40, status: 'pending', date: '2023-05-10' }, | |
| { id: '#1007', customer: 'David Taylor', amount: 320.80, status: 'completed', date: '2023-05-09' }, | |
| { id: '#1008', customer: 'Jessica Anderson', amount: 55.25, status: 'completed', date: '2023-05-08' } | |
| ]; | |
| const tableBody = document.getElementById('transactionsTable'); | |
| tableBody.innerHTML = ''; | |
| transactions.forEach(transaction => { | |
| const row = document.createElement('tr'); | |
| const statusClass = { | |
| 'completed': 'success', | |
| 'pending': 'warning', | |
| 'failed': 'danger' | |
| }[transaction.status]; | |
| row.innerHTML = ` | |
| <td>${transaction.id}</td> | |
| <td>${transaction.customer}</td> | |
| <td>$${transaction.amount.toFixed(2)}</td> | |
| <td><span class="status-badge ${statusClass}">${transaction.status}</span></td> | |
| <td>${transaction.date}</td> | |
| `; | |
| tableBody.appendChild(row); | |
| }); | |
| // Add status badge styling | |
| const style = document.createElement('style'); | |
| style.textContent = ` | |
| .status-badge { | |
| padding: 0.25rem 0.5rem; | |
| border-radius: 0.25rem; | |
| font-size: 0.875rem; | |
| font-weight: 500; | |
| } | |
| .status-badge.success { | |
| background-color: rgba(75, 181, 67, 0.1); | |
| color: ${chartColors.success}; | |
| } | |
| .status-badge.warning { | |
| background-color: rgba(248, 150, 30, 0.1); | |
| color: ${chartColors.warning}; | |
| } | |
| .status-badge.danger { | |
| background-color: rgba(249, 65, 68, 0.1); | |
| color: ${chartColors.danger}; | |
| } | |
| `; | |
| document.head.appendChild(style); | |
| } | |
| // Initialize the dashboard | |
| document.addEventListener('DOMContentLoaded', function() { | |
| generateTransactions(); | |
| }); | |
| // Mobile menu toggle (for responsive design) | |
| const mobileMenuToggle = document.createElement('button'); | |
| mobileMenuToggle.className = 'btn btn-primary mobile-menu-toggle'; | |
| mobileMenuToggle.innerHTML = '<i data-feather="menu"></i>'; | |
| mobileMenuToggle.addEventListener('click', function() { | |
| document.querySelector('.sidebar').classList.toggle('active'); | |
| }); | |
| // Add mobile menu toggle to header for mobile devices | |
| if (window.innerWidth <= 768) { | |
| document.querySelector('.header').prepend(mobileMenuToggle); | |
| feather.replace(); | |
| } | |
| // Handle window resize | |
| window.addEventListener('resize', function() { | |
| if (window.innerWidth <= 768) { | |
| if (!document.querySelector('.mobile-menu-toggle')) { | |
| document.querySelector('.header').prepend(mobileMenuToggle); | |
| feather.replace(); | |
| } | |
| } else { | |
| const toggle = document.querySelector('.mobile-menu-toggle'); | |
| if (toggle) { | |
| toggle.remove(); | |
| } | |
| document.querySelector('.sidebar').classList.remove('active'); | |
| } | |
| }); | |
| </script> | |
| </body> | |
| </html> |