Spaces:
Running
Running
| // Theme Management | |
| const themeToggle = () => { | |
| const html = document.documentElement; | |
| const isDark = html.classList.contains('dark'); | |
| if (isDark) { | |
| html.classList.remove('dark'); | |
| html.classList.add('light'); | |
| localStorage.setItem('theme', 'light'); | |
| } else { | |
| html.classList.remove('light'); | |
| html.classList.add('dark'); | |
| localStorage.setItem('theme', 'dark'); | |
| } | |
| updateChartColors(); | |
| }; | |
| // Check system preference on load | |
| if (localStorage.getItem('theme') === 'dark' || (!localStorage.getItem('theme') && window.matchMedia('(prefers-color-scheme: dark)').matches)) { | |
| document.documentElement.classList.add('dark'); | |
| } else { | |
| document.documentElement.classList.remove('dark'); | |
| } | |
| // Portfolio Chart Data | |
| const portfolioData = [ | |
| { asset: 'Bitcoin', value: 45, color: 'bg-primary-500' }, | |
| { asset: 'Ethereum', value: 30, color: 'bg-secondary-500' }, | |
| { asset: 'Solana', value: 15, color: 'bg-purple-500' }, | |
| { asset: 'USDT', value: 10, color: 'bg-emerald-500' } | |
| ]; | |
| // Render Chart | |
| function renderChart() { | |
| const chartContainer = document.getElementById('portfolioChart'); | |
| if (!chartContainer) return; | |
| chartContainer.innerHTML = ''; | |
| portfolioData.forEach((item, index) => { | |
| const bar = document.createElement('div'); | |
| bar.className = `chart-bar w-full ${item.color} rounded-t-lg opacity-90 hover:opacity-100 cursor-pointer relative group`; | |
| bar.style.height = '0%'; | |
| bar.innerHTML = ` | |
| <div class="absolute -top-8 left-1/2 transform -translate-x-1/2 bg-slate-800 text-white text-xs px-2 py-1 rounded opacity-0 group-hover:opacity-100 transition-opacity whitespace-nowrap"> | |
| ${item.asset}: ${item.value}% | |
| </div> | |
| `; | |
| chartContainer.appendChild(bar); | |
| // Animate height after small delay | |
| setTimeout(() => { | |
| bar.style.height = `${item.value * 2}%`; | |
| }, index * 100 + 100); | |
| }); | |
| } | |
| // Update chart colors based on theme | |
| function updateChartColors() { | |
| // Force re-render to adjust any theme-specific colors if needed | |
| renderChart(); | |
| } | |
| // Modal Functions | |
| function openModal(type) { | |
| const overlay = document.getElementById('modalOverlay'); | |
| const modals = document.querySelectorAll('.modal-content'); | |
| modals.forEach(m => m.classList.add('hidden')); | |
| const targetModal = document.getElementById(type + 'Modal'); | |
| if (targetModal) { | |
| targetModal.classList.remove('hidden'); | |
| overlay.classList.remove('hidden'); | |
| // Trigger reflow for animation | |
| void overlay.offsetWidth; | |
| overlay.classList.remove('opacity-0'); | |
| targetModal.classList.remove('scale-95'); | |
| targetModal.classList.add('scale-100'); | |
| } | |
| } | |
| function closeModal() { | |
| const overlay = document.getElementById('modalOverlay'); | |
| const modals = document.querySelectorAll('.modal-content'); | |
| overlay.classList.add('opacity-0'); | |
| modals.forEach(m => { | |
| m.classList.remove('scale-100'); | |
| m.classList.add('scale-95'); | |
| }); | |
| setTimeout(() => { | |
| overlay.classList.add('hidden'); | |
| modals.forEach(m => m.classList.add('hidden')); | |
| }, 300); | |
| } | |
| // Close modal on outside click | |
| document.getElementById('modalOverlay')?.addEventListener('click', (e) => { | |
| if (e.target.id === 'modalOverlay') { | |
| closeModal(); | |
| } | |
| }); | |
| // Toast Notification | |
| function showToast(message, type = 'success') { | |
| const toast = document.getElementById('toast'); | |
| const toastMessage = document.getElementById('toastMessage'); | |
| toastMessage.textContent = message; | |
| // Update icon based on type | |
| const icon = toast.querySelector('i'); | |
| if (type === 'error') { | |
| icon.setAttribute('data-feather', 'alert-circle'); | |
| icon.classList.remove('text-emerald-400'); | |
| icon.classList.add('text-red-400'); | |
| } else { | |
| icon.setAttribute('data-feather', 'check-circle'); | |
| icon.classList.remove('text-red-400'); | |
| icon.classList.add('text-emerald-400'); | |
| } | |
| feather.replace(); | |
| toast.classList.remove('translate-y-20', 'opacity-0'); | |
| setTimeout(() => { | |
| toast.classList.add('translate-y-20', 'opacity-0'); | |
| }, 3000); | |
| } | |
| // Handle Send Form | |
| function handleSend(e) { | |
| e.preventDefault(); | |
| closeModal(); | |
| // Simulate processing | |
| setTimeout(() => { | |
| showToast('Transaction sent successfully!'); | |
| updateBalance(-0.5); // Simulate balance change | |
| }, 500); | |
| } | |
| // Copy Address | |
| function copyAddress() { | |
| navigator.clipboard.writeText('0x71C7656EC7ab88b098defB751B7401B5f6d8976F'); | |
| showToast('Address copied to clipboard!'); | |
| } | |
| // Balance Update Simulation | |
| let currentBalance = 24589.42; | |
| function updateBalance(change) { | |
| currentBalance += change; | |
| const balanceElement = document.querySelector('.balance-amount'); | |
| if (balanceElement) { | |
| animateValue(balanceElement, currentBalance - change, currentBalance, 1000); | |
| } | |
| } | |
| function animateValue(obj, start, end, duration) { | |
| let startTimestamp = null; | |
| const step = (timestamp) => { | |
| if (!startTimestamp) startTimestamp = timestamp; | |
| const progress = Math.min((timestamp - startTimestamp) / duration, 1); | |
| const value = progress * (end - start) + start; | |
| obj.innerHTML = '$' + value.toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 }); | |
| if (progress < 1) { | |
| window.requestAnimationFrame(step); | |
| } | |
| }; | |
| window.requestAnimationFrame(step); | |
| } | |
| // Simulate live price updates | |
| setInterval(() => { | |
| const change = (Math.random() - 0.5) * 100; | |
| currentBalance += change; | |
| const balanceElement = document.querySelector('.balance-amount'); | |
| if (balanceElement) { | |
| balanceElement.innerHTML = '$' + currentBalance.toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 }); | |
| } | |
| // Update percentage indicator | |
| const percentChange = document.querySelector('.percent-change'); | |
| if (percentChange) { | |
| const isPositive = change > 0; | |
| percentChange.innerHTML = ` | |
| <i data-feather="trend-${isPositive ? 'up' : 'down'}" class="w-4 h-4 inline"></i> | |
| ${Math.abs((change / currentBalance * 100)).toFixed(2)}% | |
| `; | |
| percentChange.className = `percent-change text-sm font-medium flex items-center gap-1 ${isPositive ? 'text-emerald-500' : 'text-red-500'}`; | |
| feather.replace(); | |
| } | |
| }, 5000); | |
| // Initialize | |
| document.addEventListener('DOMContentLoaded', () => { | |
| renderChart(); | |
| feather.replace(); | |
| // Add keyboard shortcuts | |
| document.addEventListener('keydown', (e) => { | |
| if (e.key === 'Escape') closeModal(); | |
| }); | |
| }); | |
| // Export functions for global access | |
| window.themeToggle = themeToggle; | |
| window.openModal = openModal; | |
| window.closeModal = closeModal; | |
| window.handleSend = handleSend; | |
| window.copyAddress = copyAddress; | |
| window.showToast = showToast; |