Spaces:
Running
Running
<!DOCTYPE html> <html lang="en"> <head> <title>TradePulse: Online Brokerage</title> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta charset="utf-8" /> <meta name="description" content="Trade stocks, ETFs, and crypto with TradePulse's online brokerage platform" /> <script src="https://cdn.tailwindcss.com"></script> <script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.3/dist/chart.min.js"></script> <style> input:focus { outline: 2px solid #1d4ed8; } .error { border-color: #ef4444; }
@keyframes
fadeIn { from { opacity: 0; } to { opacity: 1; } } .fade-in { animation: fadeIn 0.5s ease-in; } .autocomplete-suggestions { position: absolute; background: white; border: 1px solid #d1d5db; max-height: 150px; overflow-y: auto; width: 100%; z-index: 10; } .autocomplete-suggestions div { padding: 8px; cursor: pointer; } .autocomplete-suggestions div:hover { background: #f3f4f6; } </style> </head> <body class="flex flex-col min-h-screen bg-gray-100 font-sans transition-colors duration-300" id="theme-body"> <!-- Header --> <header class="bg-blue-800 text-white py-4 shadow-md"> <div class="container mx-auto px-6 flex justify-between items-center"> <h1 class="text-xl font-bold">TradePulse</h1> <nav class="flex items-center space-x-4"> <a href="#home" class="hover:underline">Home</a> <a href="#dashboard" class="hover:underline">Dashboard</a> <a href="#trade" class="hover:underline">Trade</a> <button id="theme-toggle" class="bg-blue-600 px-4 py-2 rounded-md hover:bg-blue-700">Dark Mode</button> <button class="bg-blue-600 px-4 py-2 rounded-md hover:bg-blue-700">Login</button> </nav> </div> </header> <!-- Hero Section --> <section id="home" class="bg-blue-50 py-12 text-center"> <div class="container mx-auto px-6"> <span class="text-xs rounded-full mb-2 inline-block px-2 py-1 border border-blue-500/15 bg-blue-500/15 text-blue-500">🔥 Start Investing Today</span> <h2 class="text-3xl lg:text-5xl font-bold text-gray-800"> <span class="text-xl lg:text-3xl text-gray-400 block font-medium">Your Wealth, Your Way,</span> Trade with TradePulse. </h2> <p class="mt-4 text-gray-600 max-w-2xl mx-auto">Buy and sell stocks, ETFs, and cryptocurrencies with zero commissions and real-time insights.</p> <button onclick="alert('Please verify your identity to start trading.')" class="mt-6 bg-blue-600 text-white px-6 py-3 rounded-md hover:bg-blue-700">Get Started</button> </div> <img src="https://enzostvs-deepsite.hf.space/arrow.svg" alt="Decorative arrow" class="absolute bottom-8 left-0 w-[100px] transform rotate-[30deg]" /> </section> <!-- Dashboard Section --> <section id="dashboard" class="py-12 bg-white"> <div class="container mx-auto px-6"> <h3 class="text-2xl font-bold text-gray-800 text-center">Your Dashboard</h3> <div class="mt-6 grid grid-cols-1 lg:grid-cols-3 gap-6"> <!-- Portfolio Overview --> <div class="bg-gray-50 p-6 rounded-lg shadow-md"> <h4 class="text-lg font-semibold text-gray-700">Portfolio Value</h4> <p class="text-3xl font-bold text-blue-600 mt-2">$12,345.67</p> <p class="text-sm text-gray-500">+2.3% ($280.45) today</p> <canvas id="portfolio-chart" class="mt-4" aria-label="Portfolio allocation chart"></canvas> </div> <!-- Watchlist --> <div class="bg-gray-50 p-6 rounded-lg shadow-md"> <h4 class="text-lg font-semibold text-gray-700">Watchlist</h4> <ul class="mt-4 space-y-2"> <li class="flex justify-between text-sm"> <span>Apple (AAPL)</span> <span class="text-blue-600">+1.2% ($235.40)</span> </li> <li class="flex justify-between text-sm"> <span>Tesla (TSLA)</span> <span class="text-red-600">-0.8% ($420.15)</span> </li> <li class="flex justify-between text-sm"> <span>Bitcoin (BTC)</span> <span class="text-blue-600">+3.5% ($65,200.00)</span> </li> </ul> </div> <!-- Market News --> <div class="bg-gray-50 p-6 rounded-lg shadow-md"> <h4 class="text-lg font-semibold text-gray-700">Market News</h4> <ul class="mt-4 space-y-2 text-sm text-gray-600"> <li>Tech stocks rally as AI demand surges.</li> <li>Fed signals steady interest rates for 2025.</li> <li>Bitcoin hits new high amid ETF approvals.</li> </ul> </div> </div> <p class="mt-4 text-center text-sm text-gray-500">Available Cash: <span class="font-medium">$5,000.00</span></p> </div> </section> <!-- Trade Section --> <section id="trade" class="py-12 bg-gray-100"> <div class="container mx-auto px-6"> <h3 class="text-2xl font-bold text-gray-800 text-center">Trade Assets</h3> <form id="trade-form" class="mt-6 max-w-md mx-auto bg-white p-6 rounded-lg shadow-md relative" novalidate> <div class="mb-4"> <label for="asset-search" class="block text-sm font-medium text-gray-700">Search Asset <span title="Enter stock or crypto ticker" class="text-blue-500 cursor-help">ℹ️</span></label> <input id="asset-search" type="text" placeholder="e.g., AAPL, Bitcoin" class="w-full p-2 border border-gray-300 rounded-md" aria-describedby="asset-error" autocomplete="off" /> <div id="autocomplete-suggestions" class="autocomplete-suggestions hidden"></div> <p id="asset-error" class="text-sm text-red-500 hidden"></p> </div> <div class="mb-4"> <label for="quantity" class="block text-sm font-medium text-gray-700">Quantity</label> <input id="quantity" type="number" step="1" min="1" placeholder="e.g., 10" class="w-full p-2 border border-gray-300 rounded-md" aria-describedby="quantity-error" required /> <p id="quantity-error" class="text-sm text-red-500 hidden"></p> </div> <div class="mb-4"> <label for="order-type" class="block text-sm font-medium text-gray-700">Order Type</label> <select id="order-type" class="w-full p-2 border border-gray-300 rounded-md"> <option value="buy">Buy</option> <option value="sell">Sell</option> </select> </div> <button type="submit" class="w-full bg-blue-600 text-white p-2 rounded-md hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500" > Place Order </button> </form> <p id="trade-result" class="mt-4 text-center text-lg text-gray-700 fade-in" role="alert"></p> </div> </section> <!-- Footer --> <footer class="bg-blue-800 text-white py-4 mt-auto"> <div class="container mx-auto px-6 text-center"> <p class="text-sm">TradePulse is a demo brokerage platform for educational purposes. Investing involves risks, including loss of principal. Consult a financial advisor.</p> <p class="text-sm mt-2">© 2025 TradePulse. All rights reserved.</p> </div> </footer> <!-- JavaScript --> <scriptPILOTscript> // DOM Elements const tradeForm = document.getElementById('trade-form'); const inputs = { asset: document.getElementById('asset-search'), quantity: document.getElementById('quantity'), }; const errors = { asset: document.getElementById('asset-error'), quantity: document.getElementById('quantity-error'), }; const orderType = document.getElementById('order-type'); const tradeResult = document.getElementById('trade-result'); const suggestions = document.getElementById('autocomplete-suggestions'); const themeToggle body = document.getElementById('theme-body'); const themeToggle = document.getElementById('theme-toggle'); let chartInstance = null; // Mock asset data const assets = [ { ticker: 'aapl', name: 'Apple', price: 235.4 }, { ticker: 'tsla', name: 'Tesla', price: 420.15 }, { ticker: 'btc', name: 'Bitcoin', price: 65200.0 }, { ticker: 'spy', name: 'SPDR S&P 500 ETF', price: 550.2 }, ]; // Input validation function validateInput(id, value) { if (id === 'asset') { const asset = value.toLowerCase().trim(); return !asset || !assets.some(a => a.ticker === asset) ? 'Please enter a valid asset (e.g., AAPL, TSLA, BTC, SPY).' : ''; } if (!value || value <= 0) { return 'Please enter a positive number.'; } return ''; } // Update error display function updateError(id, message) { errors[id].textContent = message; errors[id].classList.toggle('hidden', !message); inputs[id].classList.toggle('error', !!message); } // Simulate trade function simulateTrade(asset, quantity, type) { try { const assetData = assets.find(a => a.ticker === asset.toLowerCase()); if (!assetData) throw new Error('Unknown asset.'); const total = (assetData.price * quantity).toFixed(2); return `Order placed: ${type.toUpperCase()} ${quantity} ${assetData.name} (${asset.toUpperCase()}) for $${total}`; } catch (error) { console.error('Trade error:', error); return null; } } // Autocomplete suggestions function showSuggestions(value) { suggestions.innerHTML = ''; if (!value) { suggestions.classList.add('hidden'); return; } const matches = assets.filter(a => a.ticker.includes(value.toLowerCase()) || a.name.toLowerCase().includes(value.toLowerCase())); if (matches.length === 0) { suggestions.classList.add('hidden'); return; } matches.forEach(asset => { const div = document.createElement('div'); div.textContent = `${asset.name} (${asset.ticker.toUpperCase()})`; div.onclick = () => { inputs.asset.value = asset.ticker; suggestions.classList.add('hidden'); updateError('asset', validateInput('asset', asset.ticker)); }; suggestions.appendChild(div); }); suggestions.classList.remove('hidden'); } // Render portfolio chart function renderPortfolioChart() { if (chartInstance) chartInstance.destroy(); new Chart(document.getElementById('portfolio-chart'), { type: 'pie', data: { labels: ['Stocks', 'ETFs', 'Crypto'], datasets: [{ data: [8500, 3200, 645.67], backgroundColor: ['#1d4ed8', '#3b82f6', '#93c5fd'], }], }, options: { responsive: true, plugins: { legend: { position: 'bottom' } }, }, }); } // Theme toggle let isDark = localStorage.getItem('theme') === 'dark'; function updateTheme() { body.classList.toggle('dark', isDark); body.classList.toggle('bg-gray-100', !isDark); body.classList.toggle('bg-gray-900', isDark); themeToggle.textContent = isDark ? 'Light Mode' : 'Dark Mode'; localStorage.setItem('theme', isDark ? 'dark' : 'light'); } updateTheme(); themeToggle.addEventListener('click', () => { isDark = !isDark; updateTheme(); }); // Form submission tradeForm.addEventListener('submit', (event) => { event.preventDefault(); const asset = inputs.asset.value; const quantity = parseFloat(inputs.quantity.value); const type = orderType.value; const assetError = validateInput('asset', asset); const quantityError = validateInput('quantity', quantity); updateError('asset', assetError); updateError('quantity', quantityError); if (!assetError && !quantityError) { const result = simulateTrade(asset, quantity, type); if (result) { tradeResult.textContent = result; tradeResult.classList.add('text-gray-700', 'fade-in'); suggestions.classList.add('hidden'); } else { tradeResult.textContent = 'Error placing order. Please try again.'; tradeResult.classList.add('text-red-500'); } } else { tradeResult.textContent = ''; } }); // Real-time validation and autocomplete const debounce = (fn, delay) => { let timeout; return (...args) => { clearTimeout(timeout); timeout = setTimeout(() => fn(...args), delay); }; }; inputs.asset.addEventListener('input', debounce(() => { const value = inputs.asset.value; updateError('asset', validateInput('asset', value)); showSuggestions(value); }, 300)); inputs.quantity.addEventListener('input', debounce(() => { const value = parseFloat(inputs.quantity.value); updateError('quantity', validateInput('quantity', value)); }, 300)); // Initialize chart renderPortfolioChart(); </script> </body> </html> - Initial Deployment
c4e5937
verified