|
|
| |
| document.addEventListener('DOMContentLoaded', async () => { |
| |
| const timeframe = document.querySelector('select').value; |
| const data = await fetchDashboardData(timeframe); |
| updateDashboard(data); |
| |
| const tooltips = document.querySelectorAll('[data-tooltip]'); |
| tooltips.forEach(tooltip => { |
| tooltip.addEventListener('mouseenter', () => { |
| const tooltipText = tooltip.getAttribute('data-tooltip'); |
| const tooltipElement = document.createElement('div'); |
| tooltipElement.className = 'tooltip-element absolute bg-gray-900 text-white text-sm px-2 py-1 rounded'; |
| tooltipElement.textContent = tooltipText; |
| tooltip.appendChild(tooltipElement); |
| |
| setTimeout(() => { |
| tooltipElement.classList.add('opacity-0'); |
| setTimeout(() => tooltipElement.remove(), 300); |
| }, 2000); |
| }); |
| }); |
| |
| |
| document.querySelectorAll('a[href^="#"]').forEach(anchor => { |
| anchor.addEventListener('click', function (e) { |
| e.preventDefault(); |
| document.querySelector(this.getAttribute('href')).scrollIntoView({ |
| behavior: 'smooth' |
| }); |
| }); |
| }); |
| }); |
| |
| async function fetchDashboardData(timeframe = '30d') { |
| try { |
| const response = await fetch(`/api/dashboard?timeframe=${timeframe}`); |
| if (!response.ok) throw new Error('Network response was not ok'); |
| return await response.json(); |
| } catch (error) { |
| console.error('Error fetching dashboard data:', error); |
| console.error('Error fetching dashboard data:', error); |
| |
| return { |
| topCategories: [ |
| { name: 'AI Development', value: 32 }, |
| { name: 'Scientific Research', value: 24 }, |
| { name: 'Business Strategy', value: 18 }, |
| { name: 'Creative Arts', value: 12 }, |
| { name: 'Technical Solutions', value: 9 }, |
| { name: 'Other', value: 5 } |
| ], |
| revenueOpportunities: [ |
| { name: 'AI Consulting Services', value: 1200000 }, |
| { name: 'Premium API Access', value: 850000 }, |
| { name: 'Custom Model Training', value: 1800000 }, |
| { name: 'Enterprise Solutions', value: 2500000 } |
| ] |
| }; |
| } |
| } |
| |
| function updateDashboard(data) { |
| |
| const topPieChart = Chart.getChart('topPieChart'); |
| topPieChart.data.datasets[0].data = data.topCategories.map(c => c.value); |
| topPieChart.update(); |
| |
| |
| const revenueContainer = document.querySelector('.grid-cols-4'); |
| if (revenueContainer && data.revenueOpportunities) { |
| |
| revenueContainer.innerHTML = ''; |
| |
| |
| data.revenueOpportunities.forEach(opp => { |
| const metricCard = document.createElement('div'); |
| metricCard.className = 'bg-white p-6 rounded-xl shadow-sm border border-gray-100'; |
| metricCard.innerHTML = ` |
| <div class="flex justify-between items-start"> |
| <div> |
| <p class="text-gray-500">${opp.name}</p> |
| <h3 class="text-2xl font-bold text-gray-800 mt-1">${formatNumber(opp.value)}</h3> |
| </div> |
| <div class="bg-indigo-100 p-2 rounded-lg"> |
| <i data-feather="dollar-sign" class="text-indigo-600 w-5 h-5"></i> |
| </div> |
| </div> |
| <p class="text-green-500 text-sm mt-2 flex items-center"> |
| <i data-feather="trending-up" class="w-4 h-4 mr-1"></i> |
| Potential revenue |
| </p> |
| `; |
| revenueContainer.appendChild(metricCard); |
| }); |
| |
| |
| feather.replace(); |
| } |
| } |
|
|
| |
| function formatNumber(num, decimals = 1) { |
| if (num >= 1000000000) { |
| return (num / 1000000000).toFixed(1) + 'B'; |
| } |
| if (num >= 1000000) { |
| return (num / 1000000).toFixed(1) + 'M'; |
| } |
| if (num >= 1000) { |
| return (num / 1000).toFixed(1) + 'K'; |
| } |
| return num.toString(); |
| } |