Spaces:
Running
Running
Download script.js from dreepj/monetization-toolkit: direct link, hf CLI and curl.
- Browser
- Download file 19.1 kB
-
https://huggingface.co/spaces/dreepj/monetization-toolkit/resolve/main/script.js
- Command line
-
hf download hf://spaces/dreepj/monetization-toolkit/script.js
-
curl -L -o script.js https://huggingface.co/spaces/dreepj/monetization-toolkit/resolve/main/script.js
19.1 kB
| // Monetization Toolkit JavaScript | |
| // Initialize the application | |
| document.addEventListener('DOMContentLoaded', function() { | |
| initializeApp(); | |
| setupEventListeners(); | |
| initializeCharts(); | |
| updateDashboardData(); | |
| // Handle hash-based navigation | |
| window.addEventListener('hashchange', function() { | |
| const section = window.location.hash.substring(1); | |
| if (section) { | |
| showSection(section); | |
| } | |
| }); | |
| // Initial section based on hash | |
| if (window.location.hash) { | |
| showSection(window.location.hash.substring(1)); | |
| } | |
| }); | |
| // Global variables | |
| let currentSection = 'dashboard'; | |
| let charts = {}; | |
| let timeRange = '7d'; | |
| // Initialize the application | |
| function initializeApp() { | |
| // Set default section | |
| showSection('dashboard'); | |
| // Initialize with sample data | |
| updateKPIs(); | |
| updateCharts(); | |
| // Set up periodic updates | |
| setInterval(updateKPIs, 30000); // Update every 30 seconds | |
| } | |
| // Setup event listeners | |
| function setupEventListeners() { | |
| // Navigation | |
| document.getElementById('region-select').addEventListener('change', function() { | |
| updateRegionData(this.value); | |
| }); | |
| // A/B Test Form | |
| document.getElementById('ab-test-form').addEventListener('submit', function(e) { | |
| e.preventDefault(); | |
| createNewTest(); | |
| }); | |
| // Modal buttons | |
| document.getElementById('watch-ad-btn').addEventListener('click', function() { | |
| simulateAdWatching(); | |
| }); | |
| document.getElementById('complete-purchase-btn').addEventListener('click', function() { | |
| completePurchase(); | |
| }); | |
| // Ad modal close on backdrop click | |
| document.getElementById('ad-modal').addEventListener('click', function(e) { | |
| if (e.target === this) closeAdModal(); | |
| }); | |
| document.getElementById('purchase-modal').addEventListener('click', function(e) { | |
| if (e.target === this) closePurchaseModal(); | |
| }); | |
| } | |
| // Section navigation | |
| function showSection(sectionName) { | |
| // Hide all sections | |
| const sections = document.querySelectorAll('.content-section'); | |
| sections.forEach(section => { | |
| section.classList.add('hidden'); | |
| }); | |
| // Show selected section | |
| document.getElementById(sectionName).classList.remove('hidden'); | |
| // Update navigation | |
| const navButtons = document.querySelectorAll('.nav-btn'); | |
| navButtons.forEach(btn => { | |
| btn.classList.remove('active'); | |
| }); | |
| event.target.classList.add('active'); | |
| currentSection = sectionName; | |
| // Update charts if needed | |
| if (sectionName === 'analytics') { | |
| updateAnalyticsCharts(); | |
| } | |
| } | |
| // Update KPIs | |
| function updateKPIs() { | |
| const kpis = { | |
| 'daily-revenue': generateRandomValue(2500, 3200, '$'), | |
| 'active-users': generateRandomValue(14500, 15800, ''), | |
| 'conversion-rate': generateRandomValue(2.8, 3.6, '%'), | |
| 'arpu': generateRandomValue(0.15, 0.22, '$') | |
| }; | |
| Object.keys(kpis).forEach(id => { | |
| const element = document.getElementById(id); | |
| if (element) { | |
| animateValue(element, element.textContent, kpis[id]); | |
| } | |
| }); | |
| } | |
| // Generate random values for simulation | |
| function generateRandomValue(min, max, prefix = '') { | |
| const value = (Math.random() * (max - min) + min).toFixed(max < 10 ? 2 : 0); | |
| return prefix + value; | |
| } | |
| // Animate value changes | |
| function animateValue(element, start, end) { | |
| const startTime = performance.now(); | |
| const duration = 1000; | |
| function updateValue(currentTime) { | |
| const elapsed = currentTime - startTime; | |
| const progress = Math.min(elapsed / duration, 1); | |
| // Simple interpolation | |
| const startNum = parseFloat(start.replace(/[^\d.-]/g, '')) || 0; | |
| const endNum = parseFloat(end.replace(/[^\d.-]/g, '')) || 0; | |
| const current = startNum + (endNum - startNum) * progress; | |
| const prefix = start.match(/^[^\d]*/)?.[0] || ''; | |
| const suffix = start.match(/[^\d]*$/)?.[0] || ''; | |
| element.textContent = prefix + current.toFixed(start.includes('%') ? 2 : start.includes('$') && startNum < 1 ? 3 : 0) + suffix; | |
| if (progress < 1) { | |
| requestAnimationFrame(updateValue); | |
| } | |
| } | |
| requestAnimationFrame(updateValue); | |
| } | |
| // Initialize Charts | |
| function initializeCharts() { | |
| // Revenue Chart | |
| const revenueCtx = document.getElementById('revenue-chart'); | |
| if (revenueCtx) { | |
| charts.revenue = new Chart(revenueCtx, { | |
| type: 'line', | |
| data: { | |
| labels: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'], | |
| datasets: [{ | |
| label: 'Revenue', | |
| data: generateChartData(7, 2000, 3000), | |
| borderColor: '#ec4899', | |
| backgroundColor: 'rgba(236, 72, 153, 0.1)', | |
| tension: 0.4, | |
| fill: true | |
| }] | |
| }, | |
| options: { | |
| responsive: true, | |
| plugins: { | |
| legend: { | |
| display: false | |
| } | |
| }, | |
| scales: { | |
| y: { | |
| beginAtZero: false, | |
| ticks: { | |
| callback: function(value) { | |
| return '$' + value; | |
| } | |
| } | |
| } | |
| } | |
| } | |
| }); | |
| } | |
| // User Chart | |
| const userCtx = document.getElementById('user-chart'); | |
| if (userCtx) { | |
| charts.user = new Chart(userCtx, { | |
| type: 'bar', | |
| data: { | |
| labels: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'], | |
| datasets: [{ | |
| label: 'New Users', | |
| data: generateChartData(7, 500, 1000), | |
| backgroundColor: '#14b8a6', | |
| borderRadius: 4 | |
| }] | |
| }, | |
| options: { | |
| responsive: true, | |
| plugins: { | |
| legend: { | |
| display: false | |
| } | |
| }, | |
| scales: { | |
| y: { | |
| beginAtZero: true | |
| } | |
| } | |
| } | |
| }); | |
| } | |
| // Ads Performance Chart | |
| const adsCtx = document.getElementById('ads-performance-chart'); | |
| if (adsCtx) { | |
| charts.ads = new Chart(adsCtx, { | |
| type: 'doughnut', | |
| data: { | |
| labels: ['Completed', 'Skipped', 'Failed'], | |
| datasets: [{ | |
| data: [75, 20, 5], | |
| backgroundColor: ['#14b8a6', '#ec4899', '#f3f4f6'], | |
| borderWidth: 0 | |
| }] | |
| }, | |
| options: { | |
| responsive: true, | |
| plugins: { | |
| legend: { | |
| position: 'bottom' | |
| } | |
| } | |
| } | |
| }); | |
| } | |
| // Purchase Chart | |
| const purchaseCtx = document.getElementById('purchase-chart'); | |
| if (purchaseCtx) { | |
| charts.purchase = new Chart(purchaseCtx, { | |
| type: 'pie', | |
| data: { | |
| labels: ['Starter Pack', 'Value Pack', 'Mega Pack'], | |
| datasets: [{ | |
| data: [25, 45, 30], | |
| backgroundColor: ['#ec4899', '#14b8a6', '#f3f4f6'], | |
| borderWidth: 0 | |
| }] | |
| }, | |
| options: { | |
| responsive: true, | |
| plugins: { | |
| legend: { | |
| position: 'bottom' | |
| } | |
| } | |
| } | |
| }); | |
| } | |
| // Analytics Charts | |
| initializeAnalyticsCharts(); | |
| } | |
| // Initialize Analytics Charts | |
| function initializeAnalyticsCharts() { | |
| // Revenue Source Chart | |
| const revenueSourceCtx = document.getElementById('revenue-source-chart'); | |
| if (revenueSourceCtx) { | |
| charts.revenueSource = new Chart(revenueSourceCtx, { | |
| type: 'bar', | |
| data: { | |
| labels: ['Rewarded Ads', 'In-App Purchases', 'Subscriptions'], | |
| datasets: [{ | |
| label: 'Revenue ($)', | |
| data: [15000, 25000, 8000], | |
| backgroundColor: ['#ec4899', '#14b8a6', '#f3f4f6'], | |
| borderRadius: 4 | |
| }] | |
| }, | |
| options: { | |
| responsive: true, | |
| indexAxis: 'y', | |
| plugins: { | |
| legend: { | |
| display: false | |
| } | |
| } | |
| } | |
| }); | |
| } | |
| // Retention Chart | |
| const retentionCtx = document.getElementById('retention-chart'); | |
| if (retentionCtx) { | |
| charts.retention = new Chart(retentionCtx, { | |
| type: 'line', | |
| data: { | |
| labels: ['Day 1', 'Day 3', 'Day 7', 'Day 14', 'Day 30'], | |
| datasets: [{ | |
| label: 'Retention Rate', | |
| data: [100, 65, 45, 35, 28], | |
| borderColor: '#14b8a6', | |
| backgroundColor: 'rgba(20, 184, 166, 0.1)', | |
| tension: 0.4, | |
| fill: true | |
| }] | |
| }, | |
| options: { | |
| responsive: true, | |
| plugins: { | |
| legend: { | |
| display: false | |
| } | |
| }, | |
| scales: { | |
| y: { | |
| beginAtZero: true, | |
| max: 100, | |
| ticks: { | |
| callback: function(value) { | |
| return value + '%'; | |
| } | |
| } | |
| } | |
| } | |
| } | |
| }); | |
| } | |
| } | |
| // Generate chart data | |
| function generateChartData(days, min, max) { | |
| const data = []; | |
| for (let i = 0; i < days; i++) { | |
| data.push(Math.floor(Math.random() * (max - min) + min)); | |
| } | |
| return data; | |
| } | |
| // Update charts | |
| function updateCharts() { | |
| Object.keys(charts).forEach(chartKey => { | |
| if (charts[chartKey]) { | |
| // Update with new data | |
| if (chartKey === 'revenue') { | |
| charts[chartKey].data.datasets[0].data = generateChartData(7, 2000, 3000); | |
| } else if (chartKey === 'user') { | |
| charts[chartKey].data.datasets[0].data = generateChartData(7, 500, 1000); | |
| } | |
| charts[chartKey].update('none'); | |
| } | |
| }); | |
| } | |
| // Update analytics charts | |
| function updateAnalyticsCharts() { | |
| // Add some animation to charts when section is shown | |
| Object.keys(charts).forEach(chartKey => { | |
| if (charts[chartKey] && charts[chartKey].canvas.closest('#analytics')) { | |
| charts[chartKey].update('active'); | |
| } | |
| }); | |
| } | |
| // Time range update | |
| function updateTimeRange(range) { | |
| timeRange = range; | |
| // Update button states | |
| const buttons = document.querySelectorAll('.time-range-btn'); | |
| buttons.forEach(btn => { | |
| btn.classList.remove('bg-pink-500', 'text-white'); | |
| btn.classList.add('bg-gray-200', 'text-gray-700'); | |
| }); | |
| event.target.classList.remove('bg-gray-200', 'text-gray-700'); | |
| event.target.classList.add('bg-pink-500', 'text-white'); | |
| // Update charts with new time range | |
| updateChartsForTimeRange(range); | |
| } | |
| // Update charts for specific time range | |
| function updateChartsForTimeRange(range) { | |
| let days, min, max; | |
| switch(range) { | |
| case '7d': | |
| days = 7; | |
| min = 2000; | |
| max = 3000; | |
| break; | |
| case '30d': | |
| days = 30; | |
| min = 1800; | |
| max = 3200; | |
| break; | |
| case '90d': | |
| days = 90; | |
| min = 1600; | |
| max = 3400; | |
| break; | |
| } | |
| if (charts.revenue) { | |
| charts.revenue.data.labels = generateTimeLabels(days); | |
| charts.revenue.data.datasets[0].data = generateChartData(days, min, max); | |
| charts.revenue.update('active'); | |
| } | |
| } | |
| // Generate time labels | |
| function generateTimeLabels(days) { | |
| const labels = []; | |
| const today = new Date(); | |
| for (let i = days - 1; i >= 0; i--) { | |
| const date = new Date(today); | |
| date.setDate(date.getDate() - i); | |
| labels.push(date.toLocaleDateString('en-US', { month: 'short', day: 'numeric' })); | |
| } | |
| return labels; | |
| } | |
| // Create new A/B test | |
| function createNewTest() { | |
| const form = document.getElementById('ab-test-form'); | |
| const formData = new FormData(form); | |
| // Simulate test creation | |
| showNotification('A/B Test created successfully!', 'success'); | |
| form.reset(); | |
| // Add to active tests list (simulation) | |
| setTimeout(() => { | |
| updateActiveTests(); | |
| }, 1000); | |
| } | |
| // Update active tests list | |
| function updateActiveTests() { | |
| // This would typically fetch from an API | |
| console.log('Updating active tests...'); | |
| } | |
| // Region data update | |
| function updateRegionData(region) { | |
| // Simulate region-specific data updates | |
| showNotification(`Region changed to ${region.toUpperCase()}`, 'info'); | |
| // Update KPIs based on region | |
| updateKPIsForRegion(region); | |
| } | |
| // Update KPIs for specific region | |
| function updateKPIsForRegion(region) { | |
| const regionMultipliers = { | |
| 'global': 1.0, | |
| 'us': 1.2, | |
| 'eu': 1.1, | |
| 'asia': 0.8, | |
| 'latam': 0.6 | |
| }; | |
| const multiplier = regionMultipliers[region] || 1.0; | |
| // Update with regional data | |
| const baseValues = { | |
| 'daily-revenue': 2847, | |
| 'active-users': 15234, | |
| 'conversion-rate': 3.24, | |
| 'arpu': 0.187 | |
| }; | |
| Object.keys(baseValues).forEach(id => { | |
| const element = document.getElementById(id); | |
| if (element) { | |
| const baseValue = baseValues[id]; | |
| const newValue = baseValue * multiplier * (0.9 + Math.random() * 0.2); | |
| let formattedValue; | |
| if (id === 'daily-revenue') { | |
| formattedValue = '$' + newValue.toFixed(0); | |
| } else if (id === 'active-users') { | |
| formattedValue = Math.round(newValue).toLocaleString(); | |
| } else if (id === 'conversion-rate') { | |
| formattedValue = newValue.toFixed(2) + '%'; | |
| } else if (id === 'arpu') { | |
| formattedValue = '$' + newValue.toFixed(3); | |
| } | |
| animateValue(element, element.textContent, formattedValue); | |
| } | |
| }); | |
| } | |
| // Simulate ad watching | |
| function simulateAdWatching() { | |
| const button = document.getElementById('watch-ad-btn'); | |
| const originalText = button.textContent; | |
| button.disabled = true; | |
| button.innerHTML = '<div class="spinner mx-auto"></div>'; | |
| // Simulate ad duration | |
| setTimeout(() => { | |
| button.textContent = 'Ad Complete!'; | |
| button.classList.remove('bg-pink-500', 'hover:bg-pink-600'); | |
| button.classList.add('bg-green-500', 'hover:bg-green-600'); | |
| setTimeout(() => { | |
| closeAdModal(); | |
| showNotification('Ad watched successfully! +3 extra lives', 'success'); | |
| button.textContent = originalText; | |
| button.disabled = false; | |
| button.classList.remove('bg-green-500', 'hover:bg-green-600'); | |
| button.classList.add('bg-pink-500', 'hover:bg-pink-600'); | |
| }, 1500); | |
| }, 3000); | |
| } | |
| // Complete purchase | |
| function completePurchase() { | |
| const button = document.getElementById('complete-purchase-btn'); | |
| const originalText = button.textContent; | |
| button.disabled = true; | |
| button.innerHTML = '<div class="spinner mx-auto"></div>'; | |
| // Simulate purchase processing | |
| setTimeout(() => { | |
| button.textContent = 'Purchase Complete!'; | |
| button.classList.remove('bg-teal-500', 'hover:bg-teal-600'); | |
| button.classList.add('bg-green-500', 'hover:bg-green-600'); | |
| setTimeout(() => { | |
| closePurchaseModal(); | |
| showNotification('Purchase successful! 2,500 coins added to your account', 'success'); | |
| button.textContent = originalText; | |
| button.disabled = false; | |
| button.classList.remove('bg-green-500', 'hover:bg-green-600'); | |
| button.classList.add('bg-teal-500', 'hover:bg-teal-600'); | |
| }, 1500); | |
| }, 2000); | |
| } | |
| // Modal functions | |
| function closeAdModal() { | |
| document.getElementById('ad-modal').classList.add('hidden'); | |
| } | |
| function closePurchaseModal() { | |
| document.getElementById('purchase-modal').classList.add('hidden'); | |
| } | |
| // Show notification | |
| function showNotification(message, type = 'info') { | |
| // Create notification element | |
| const notification = document.createElement('div'); | |
| notification.className = `fixed top-4 right-4 z-50 p-4 rounded-lg shadow-lg max-w-sm transform transition-all duration-300 translate-x-full`; | |
| // Set colors based on type | |
| switch(type) { | |
| case 'success': | |
| notification.classList.add('bg-green-500', 'text-white'); | |
| break; | |
| case 'error': | |
| notification.classList.add('bg-red-500', 'text-white'); | |
| break; | |
| case 'warning': | |
| notification.classList.add('bg-yellow-500', 'text-white'); | |
| break; | |
| default: | |
| notification.classList.add('bg-blue-500', 'text-white'); | |
| } | |
| notification.innerHTML = ` | |
| <div class="flex items-center"> | |
| <div class="flex-1">${message}</div> | |
| <button onclick="this.parentElement.parentElement.remove()" class="ml-3 text-white hover:text-gray-200"> | |
| <i data-feather="x"></i> | |
| </button> | |
| </div> | |
| `; | |
| document.body.appendChild(notification); | |
| // Animate in | |
| setTimeout(() => { | |
| notification.classList.remove('translate-x-full'); | |
| }, 100); | |
| // Auto remove after 5 seconds | |
| setTimeout(() => { | |
| notification.classList.add('translate-x-full'); | |
| setTimeout(() => { | |
| if (notification.parentNode) { | |
| notification.remove(); | |
| } | |
| }, 300); | |
| }, 5000); | |
| // Refresh feather icons | |
| if (typeof feather !== 'undefined') { | |
| feather.replace(); | |
| } | |
| } | |
| // Dashboard data updates | |
| function updateDashboardData() { | |
| // Simulate real-time data updates | |
| setInterval(() => { | |
| if (currentSection === 'dashboard') { | |
| updateKPIs(); | |
| updateCharts(); | |
| } | |
| }, 10000); // Update every 10 seconds | |
| } | |
| // Export functions for testing (if needed) | |
| if (typeof module !== 'undefined' && module.exports) { | |
| module.exports = { | |
| generateRandomValue, | |
| animateValue, | |
| showNotification | |
| }; | |
| } |