Spaces:
Running
Running
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>TradePro - Personal Trading Terminal</title> | |
| <!-- Fonts --> | |
| <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet"> | |
| <!-- Icons --> | |
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> | |
| <!-- Chart.js --> | |
| <script src="https://cdn.jsdelivr.net/npm/chart.js"></script> | |
| <style> | |
| :root { | |
| --bg-dark: #0f1115; | |
| --bg-panel: #181b21; | |
| --bg-hover: #22262e; | |
| --text-primary: #ffffff; | |
| --text-secondary: #8b949e; | |
| --accent-primary: #2962ff; | |
| --accent-hover: #1e4bd8; | |
| --success: #00c853; | |
| --danger: #ff1744; | |
| --border: #2f3336; | |
| --sidebar-width: 260px; | |
| --header-height: 70px; | |
| } | |
| * { | |
| margin: 0; | |
| padding: 0; | |
| box-sizing: border-box; | |
| font-family: 'Inter', sans-serif; | |
| } | |
| body { | |
| background-color: var(--bg-dark); | |
| color: var(--text-primary); | |
| overflow-x: hidden; | |
| } | |
| /* Scrollbar */ | |
| ::-webkit-scrollbar { | |
| width: 8px; | |
| } | |
| ::-webkit-scrollbar-track { | |
| background: var(--bg-dark); | |
| } | |
| ::-webkit-scrollbar-thumb { | |
| background: #333; | |
| border-radius: 4px; | |
| } | |
| ::-webkit-scrollbar-thumb:hover { | |
| background: #555; | |
| } | |
| /* Layout */ | |
| .app-container { | |
| display: flex; | |
| min-height: 100vh; | |
| } | |
| /* Sidebar */ | |
| .sidebar { | |
| width: var(--sidebar-width); | |
| background-color: var(--bg-panel); | |
| border-right: 1px solid var(--border); | |
| display: flex; | |
| flex-direction: column; | |
| position: fixed; | |
| height: 100%; | |
| z-index: 100; | |
| transition: transform 0.3s ease; | |
| } | |
| .logo-area { | |
| height: var(--header-height); | |
| display: flex; | |
| align-items: center; | |
| padding: 0 24px; | |
| border-bottom: 1px solid var(--border); | |
| } | |
| .logo { | |
| font-size: 24px; | |
| font-weight: 700; | |
| color: var(--accent-primary); | |
| display: flex; | |
| align-items: center; | |
| gap: 10px; | |
| } | |
| .nav-links { | |
| padding: 20px 12px; | |
| flex: 1; | |
| } | |
| .nav-group { | |
| margin-bottom: 30px; | |
| } | |
| .nav-group-title { | |
| font-size: 12px; | |
| color: var(--text-secondary); | |
| text-transform: uppercase; | |
| letter-spacing: 1px; | |
| margin-bottom: 12px; | |
| padding-left: 12px; | |
| } | |
| .nav-item { | |
| display: flex; | |
| align-items: center; | |
| padding: 12px 16px; | |
| color: var(--text-secondary); | |
| text-decoration: none; | |
| border-radius: 8px; | |
| margin-bottom: 4px; | |
| transition: all 0.2s; | |
| cursor: pointer; | |
| } | |
| .nav-item i { | |
| width: 24px; | |
| font-size: 18px; | |
| } | |
| .nav-item span { | |
| margin-left: 12px; | |
| font-weight: 500; | |
| } | |
| .nav-item:hover, .nav-item.active { | |
| background-color: var(--bg-hover); | |
| color: var(--text-primary); | |
| } | |
| .nav-item.active { | |
| border-left: 3px solid var(--accent-primary); | |
| } | |
| .user-profile { | |
| padding: 20px; | |
| border-top: 1px solid var(--border); | |
| display: flex; | |
| align-items: center; | |
| gap: 12px; | |
| } | |
| .avatar { | |
| width: 40px; | |
| height: 40px; | |
| border-radius: 50%; | |
| background: linear-gradient(45deg, var(--accent-primary), #6a11cb); | |
| display: flex; | |
| justify-content: center; | |
| align-items: center; | |
| font-weight: bold; | |
| } | |
| .user-info h4 { | |
| font-size: 14px; | |
| font-weight: 600; | |
| } | |
| .user-info p { | |
| font-size: 12px; | |
| color: var(--text-secondary); | |
| } | |
| /* Main Content */ | |
| .main-content { | |
| margin-left: var(--sidebar-width); | |
| flex: 1; | |
| padding: 30px; | |
| min-height: 100vh; | |
| } | |
| /* Header */ | |
| .top-bar { | |
| display: flex; | |
| justify-content: space-between; | |
| align-items: center; | |
| margin-bottom: 30px; | |
| } | |
| .page-title { | |
| font-size: 24px; | |
| font-weight: 600; | |
| } | |
| .header-actions { | |
| display: flex; | |
| gap: 15px; | |
| } | |
| .icon-btn { | |
| background: var(--bg-panel); | |
| border: 1px solid var(--border); | |
| color: var(--text-secondary); | |
| width: 40px; | |
| height: 40px; | |
| border-radius: 8px; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| cursor: pointer; | |
| transition: all 0.2s; | |
| } | |
| .icon-btn:hover { | |
| color: var(--text-primary); | |
| border-color: var(--text-secondary); | |
| } | |
| /* Dashboard Grid */ | |
| .dashboard-grid { | |
| display: grid; | |
| grid-template-columns: repeat(4, 1fr); | |
| gap: 20px; | |
| margin-bottom: 30px; | |
| } | |
| .stat-card { | |
| background-color: var(--bg-panel); | |
| padding: 20px; | |
| border-radius: 12px; | |
| border: 1px solid var(--border); | |
| } | |
| .stat-header { | |
| display: flex; | |
| justify-content: space-between; | |
| align-items: center; | |
| margin-bottom: 15px; | |
| } | |
| .stat-title { | |
| color: var(--text-secondary); | |
| font-size: 14px; | |
| font-weight: 500; | |
| } | |
| .stat-icon { | |
| width: 32px; | |
| height: 32px; | |
| border-radius: 8px; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| font-size: 16px; | |
| } | |
| .stat-value { | |
| font-size: 24px; | |
| font-weight: 700; | |
| margin-bottom: 5px; | |
| } | |
| .stat-change { | |
| font-size: 13px; | |
| display: flex; | |
| align-items: center; | |
| gap: 4px; | |
| } | |
| .text-green { color: var(--success); } | |
| .text-red { color: var(--danger); } | |
| .bg-green-light { background: rgba(0, 200, 83, 0.15); color: var(--success); } | |
| .bg-red-light { background: rgba(255, 23, 68, 0.15); color: var(--danger); } | |
| .bg-blue-light { background: rgba(41, 98, 255, 0.15); color: var(--accent-primary); } | |
| /* Main Middle Section */ | |
| .middle-section { | |
| display: grid; | |
| grid-template-columns: 3fr 1fr; | |
| gap: 20px; | |
| margin-bottom: 30px; | |
| } | |
| /* Chart Section */ | |
| .panel { | |
| background-color: var(--bg-panel); | |
| border-radius: 12px; | |
| border: 1px solid var(--border); | |
| padding: 20px; | |
| overflow: hidden; | |
| } | |
| .panel-header { | |
| display: flex; | |
| justify-content: space-between; | |
| align-items: center; | |
| margin-bottom: 20px; | |
| } | |
| .panel-title { | |
| font-size: 18px; | |
| font-weight: 600; | |
| } | |
| .chart-container { | |
| height: 300px; | |
| position: relative; | |
| } | |
| /* Trading Form */ | |
| .trade-tabs { | |
| display: flex; | |
| margin-bottom: 20px; | |
| background: var(--bg-dark); | |
| border-radius: 8px; | |
| padding: 4px; | |
| } | |
| .trade-tab { | |
| flex: 1; | |
| text-align: center; | |
| padding: 10px; | |
| border-radius: 6px; | |
| cursor: pointer; | |
| font-weight: 500; | |
| color: var(--text-secondary); | |
| transition: all 0.2s; | |
| } | |
| .trade-tab.active { | |
| background-color: var(--accent-primary); | |
| color: white; | |
| } | |
| .trade-tab.sell.active { | |
| background-color: var(--danger); | |
| } | |
| .form-group { | |
| margin-bottom: 15px; | |
| } | |
| .form-label { | |
| display: block; | |
| margin-bottom: 8px; | |
| font-size: 13px; | |
| color: var(--text-secondary); | |
| } | |
| .form-input { | |
| width: 100%; | |
| background: var(--bg-dark); | |
| border: 1px solid var(--border); | |
| padding: 12px; | |
| border-radius: 8px; | |
| color: white; | |
| font-size: 15px; | |
| } | |
| .form-input:focus { | |
| outline: none; | |
| border-color: var(--accent-primary); | |
| } | |
| .asset-selector { | |
| display: flex; | |
| align-items: center; | |
| gap: 10px; | |
| margin-bottom: 15px; | |
| } | |
| .asset-icon { | |
| width: 36px; | |
| height: 36px; | |
| background: var(--bg-hover); | |
| border-radius: 50%; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| font-size: 18px; | |
| } | |
| .asset-details h3 { | |
| font-size: 16px; | |
| } | |
| .asset-details span { | |
| font-size: 12px; | |
| color: var(--text-secondary); | |
| } | |
| .action-btn { | |
| width: 100%; | |
| padding: 14px; | |
| border-radius: 8px; | |
| border: none; | |
| font-weight: 600; | |
| font-size: 16px; | |
| cursor: pointer; | |
| transition: transform 0.1s; | |
| margin-top: 10px; | |
| } | |
| .action-btn:active { | |
| transform: scale(0.98); | |
| } | |
| /* Tables */ | |
| .bottom-section { | |
| display: grid; | |
| grid-template-columns: 1fr 1fr; | |
| gap: 20px; | |
| } | |
| table { | |
| width: 100%; | |
| border-collapse: collapse; | |
| } | |
| th { | |
| text-align: left; | |
| padding: 12px 0; | |
| color: var(--text-secondary); | |
| font-weight: 500; | |
| font-size: 13px; | |
| border-bottom: 1px solid var(--border); | |
| } | |
| td { | |
| padding: 16px 0; | |
| border-bottom: 1px solid var(--border); | |
| font-size: 14px; | |
| } | |
| tr:last-child td { | |
| border-bottom: none; | |
| } | |
| .coin-cell { | |
| display: flex; | |
| align-items: center; | |
| gap: 10px; | |
| } | |
| .coin-icon-sm { | |
| width: 28px; | |
| height: 28px; | |
| border-radius: 50%; | |
| background: #333; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| font-size: 14px; | |
| } | |
| .positive { color: var(--success); } | |
| .negative { color: var(--danger); } | |
| /* Footer */ | |
| .footer { | |
| margin-top: 40px; | |
| text-align: center; | |
| color: var(--text-secondary); | |
| font-size: 13px; | |
| padding-top: 20px; | |
| border-top: 1px solid var(--border); | |
| } | |
| .footer a { | |
| color: var(--accent-primary); | |
| text-decoration: none; | |
| font-weight: 600; | |
| } | |
| /* Responsive */ | |
| @media (max-width: 1200px) { | |
| .dashboard-grid { | |
| grid-template-columns: repeat(2, 1fr); | |
| } | |
| .middle-section { | |
| grid-template-columns: 2fr 1fr; | |
| } | |
| } | |
| @media (max-width: 992px) { | |
| .sidebar { | |
| transform: translateX(-100%); | |
| position: fixed; | |
| } | |
| .sidebar.active { | |
| transform: translateX(0); | |
| } | |
| .main-content { | |
| margin-left: 0; | |
| } | |
| .bottom-section { | |
| grid-template-columns: 1fr; | |
| } | |
| .menu-toggle { | |
| display: flex ; | |
| } | |
| } | |
| @media (max-width: 768px) { | |
| .dashboard-grid { | |
| grid-template-columns: 1fr; | |
| } | |
| .middle-section { | |
| grid-template-columns: 1fr; | |
| } | |
| .top-bar { | |
| flex-direction: column; | |
| align-items: flex-start; | |
| gap: 15px; | |
| } | |
| } | |
| .menu-toggle { | |
| display: none; | |
| position: fixed; | |
| top: 20px; | |
| left: 20px; | |
| z-index: 200; | |
| background: var(--accent-primary); | |
| color: white; | |
| border: none; | |
| width: 40px; | |
| height: 40px; | |
| border-radius: 8px; | |
| cursor: pointer; | |
| align-items: center; | |
| justify-content: center; | |
| font-size: 20px; | |
| } | |
| .overlay { | |
| display: none; | |
| position: fixed; | |
| top: 0; | |
| left: 0; | |
| right: 0; | |
| bottom: 0; | |
| background: rgba(0,0,0,0.5); | |
| z-index: 90; | |
| } | |
| .overlay.active { | |
| display: block; | |
| } | |
| /* Animations */ | |
| @keyframes pulse { | |
| 0% { opacity: 1; } | |
| 50% { opacity: 0.5; } | |
| 100% { opacity: 1; } | |
| } | |
| .live-indicator { | |
| display: inline-block; | |
| width: 8px; | |
| height: 8px; | |
| background-color: var(--success); | |
| border-radius: 50%; | |
| margin-right: 5px; | |
| animation: pulse 2s infinite; | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <button class="menu-toggle" onclick="toggleSidebar()"> | |
| <i class="fas fa-bars"></i> | |
| </button> | |
| <div class="overlay" onclick="toggleSidebar()"></div> | |
| <div class="app-container"> | |
| <!-- Sidebar --> | |
| <aside class="sidebar" id="sidebar"> | |
| <div class="logo-area"> | |
| <div class="logo"> | |
| <i class="fas fa-chart-line"></i> | |
| <span>TradePro</span> | |
| </div> | |
| </div> | |
| <nav class="nav-links"> | |
| <div class="nav-group"> | |
| <div class="nav-group-title">Menu</div> | |
| <a class="nav-item active" onclick="switchTab('dashboard')"> | |
| <i class="fas fa-th-large"></i> | |
| <span>Dashboard</span> | |
| </a> | |
| <a class="nav-item" onclick="switchTab('portfolio')"> | |
| <i class="fas fa-briefcase"></i> | |
| <span>Portfolio</span> | |
| </a> | |
| <a class="nav-item" onclick="switchTab('market')"> | |
| <i class="fas fa-chart-bar"></i> | |
| <span>Market</span> | |
| </a> | |
| </div> | |
| <div class="nav-group"> | |
| <div class="nav-group-title">Account</div> | |
| <a class="nav-item" onclick="switchTab('history')"> | |
| <i class="fas fa-history"></i> | |
| <span>History</span> | |
| </a> | |
| <a class="nav-item" onclick="switchTab('settings')"> | |
| <i class="fas fa-cog"></i> | |
| <span>Settings</span> | |
| </a> | |
| </div> | |
| </nav> | |
| <div class="user-profile"> | |
| <div class="avatar">JD</div> | |
| <div class="user-info"> | |
| <h4>John Doe</h4> | |
| <p>Pro Trader</p> | |
| </div> | |
| </div> | |
| </aside> | |
| <!-- Main Content --> | |
| <main class="main-content"> | |
| <!-- Top Bar --> | |
| <div class="top-bar"> | |
| <div> | |
| <h1 class="page-title">Dashboard</h1> | |
| <p style="color: var(--text-secondary); font-size: 14px; margin-top: 5px;">Welcome back, Market is <span class="text-green">Open</span> <span class="live-indicator"></span></p> | |
| </div> | |
| <div class="header-actions"> | |
| <div class="icon-btn"><i class="fas fa-search"></i></div> | |
| <div class="icon-btn"><i class="fas fa-bell"></i></div> | |
| <div class="icon-btn"><i class="fas fa-envelope"></i></div> | |
| </div> | |
| </div> | |
| <!-- Stats Grid --> | |
| <div class="dashboard-grid"> | |
| <div class="stat-card"> | |
| <div class="stat-header"> | |
| <span class="stat-title">Total Balance</span> | |
| <div class="stat-icon bg-blue-light"><i class="fas fa-wallet"></i></div> | |
| </div> | |
| <div class="stat-value" id="total-balance">$124,500.00</div> | |
| <div class="stat-change text-green"> | |
| <i class="fas fa-arrow-up"></i> 2.4% <span style="color: var(--text-secondary); margin-left: 5px;">vs last 7d</span> | |
| </div> | |
| </div> | |
| <div class="stat-card"> | |
| <div class="stat-header"> | |
| <span class="stat-title">Day's P&L</span> | |
| <div class="stat-icon bg-green-light"><i class="fas fa-caret-up"></i></div> | |
| </div> | |
| <div class="stat-value" id="daily-pnl">+$1,240.50</div> | |
| <div class="stat-change text-green"> | |
| <i class="fas fa-arrow-up"></i> 1.2% <span style="color: var(--text-secondary); margin-left: 5px;">Today</span> | |
| </div> | |
| </div> | |
| <div class="stat-card"> | |
| <div class="stat-header"> | |
| <span class="stat-title">Buying Power</span> | |
| <div class="stat-icon bg-blue-light"><i class="fas fa-money-bill-wave"></i></div> | |
| </div> | |
| <div class="stat-value" id="buying-power">$45,000.00</div> | |
| <div class="stat-change" style="color: var(--text-secondary)"> | |
| <span>Available cash</span> | |
| </div> | |
| </div> | |
| <div class="stat-card"> | |
| <div class="stat-header"> | |
| <span class="stat-title">Open Positions</span> | |
| <div class="stat-icon bg-red-light"><i class="fas fa-layer-group"></i></div> | |
| </div> | |
| <div class="stat-value">8</div> | |
| <div class="stat-change" style="color: var(--text-secondary)"> | |
| <span>Across 4 Assets</span> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Middle Section: Chart & Trade --> | |
| <div class="middle-section"> | |
| <div class="panel"> | |
| <div class="panel-header"> | |
| <h3 class="panel-title">Portfolio Performance</h3> | |
| <div style="display: flex; gap: 10px;"> | |
| <span class="trade-tab active" style="padding: 6px 12px; font-size: 12px;">1D</span> | |
| <span class="trade-tab" style="padding: 6px 12px; font-size: 12px;">1W</span> | |
| <span class="trade-tab" style="padding: 6px 12px; font-size: 12px;">1M</span> | |
| <span class="trade-tab" style="padding: 6px 12px; font-size: 12px;">1Y</span> | |
| </div> | |
| </div> | |
| <div class="chart-container"> | |
| <canvas id="portfolioChart"></canvas> | |
| </div> | |
| </div> | |
| <div class="panel"> | |
| <div class="panel-header"> | |
| <h3 class="panel-title">Quick Trade</h3> | |
| </div> | |
| <div class="asset-selector"> | |
| <div class="asset-icon">BTC</div> | |
| <div class="asset-details"> | |
| <h3>Bitcoin</h3> | |
| <span>BTC/USD</span> | |
| </div> | |
| </div> | |
| <div class="trade-tabs"> | |
| <div class="trade-tab buy active" onclick="setTradeType('buy')">Buy</div> | |
| <div class="trade-tab sell" onclick="setTradeType('sell')">Sell</div> | |
| </div> | |
| <form id="trade-form" onsubmit="executeTrade(event)"> | |
| <div class="form-group"> | |
| <label class="form-label">Price (USD)</label> | |
| <input type="text" class="form-input" id="trade-price" value="64,230.50" readonly> | |
| </div> | |
| <div class="form-group"> | |
| <label class="form-label">Amount</label> | |
| <input type="number" class="form-input" id="trade-amount" placeholder="0.00"> | |
| </div> | |
| <div class="form-group"> | |
| <label class="form-label">Total</label> | |
| <input type="text" class="form-input" id="trade-total" placeholder="$0.00" readonly> | |
| </div> | |
| <button type="submit" class="action-btn" id="submit-btn">Buy BTC</button> | |
| </form> | |
| </div> | |
| </div> | |
| <!-- Bottom Section: Tables --> | |
| <div class="bottom-section"> | |
| <div class="panel"> | |
| <div class="panel-header"> | |
| <h3 class="panel-title">Holdings</h3> | |
| <a href="#" style="color: var(--accent-primary); text-decoration: none; font-size: 13px;">View All</a> | |
| </div> | |
| <table> | |
| <thead> | |
| <tr> | |
| <th>Asset</th> | |
| <th>Price</th> | |
| <th>Balance</th> | |
| <th>P&L</th> | |
| </tr> | |
| </thead> | |
| <tbody id="holdings-table"> | |
| <!-- Populated by JS --> | |
| </tbody> | |
| </table> | |
| </div> | |
| <div class="panel"> | |
| <div class="panel-header"> | |
| <h3 class="panel-title">Market Watch</h3> | |
| <i class="fas fa-star" style="color: #f1c40f;"></i> | |
| </div> | |
| <table> | |
| <thead> | |
| <tr> | |
| <th>Symbol</th> | |
| <th>Price</th> | |
| <th>24h Change</th> | |
| </tr> | |
| </thead> | |
| <tbody id="watchlist-table"> | |
| <!-- Populated by JS --> | |
| </tbody> | |
| </table> | |
| </div> | |
| </div> | |
| <div class="footer"> | |
| <p>Built with <a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank">anycoder</a></p> | |
| <p style="margin-top: 5px;">© 2023 TradePro Terminal. All rights reserved.</p> | |
| </div> | |
| </main> | |
| </div> | |
| <script> | |
| // --- Data Simulation --- | |
| const portfolioData = { | |
| balance: 124500.00, | |
| dailyPnl: 1240.50, | |
| buyingPower: 45000.00, | |
| holdings: [ | |
| { symbol: 'BTC', name: 'Bitcoin', price: 64230.50, amount: 0.5, pnl: 5.2 }, | |
| { symbol: 'ETH', name: 'Ethereum', price: 3450.20, amount: 10.5, pnl: -1.2 }, | |
| { symbol: 'AAPL', name: 'Apple Inc.', price: 178.50, amount: 50, pnl: 12.5 }, | |
| { symbol: 'TSLA', name: 'Tesla', price: 245.00, amount: 20, pnl: -3.8 } | |
| ], | |
| watchlist: [ | |
| { symbol: 'NVDA', name: 'NVIDIA', price: 890.50, change: 3.4 }, | |
| { symbol: 'MSFT', name: 'Microsoft', price: 425.10, change: 0.8 }, | |
| { symbol: 'AMZN', name: 'Amazon', price: 178.30, change: -1.2 }, | |
| { symbol: 'GOOGL', name: 'Alphabet', price: 170.40, change: 1.5 } | |
| ] | |
| }; | |
| let currentTradeType = 'buy'; | |
| let chartInstance = null; | |
| // --- Initialization --- | |
| document.addEventListener('DOMContentLoaded', () => { | |
| renderTables(); | |
| initChart(); | |
| updateLiveData(); | |
| // Listen for amount changes to update total | |
| document.getElementById('trade-amount').addEventListener('input', calculateTotal); | |
| }); | |
| // --- Functions --- | |
| function toggleSidebar() { | |
| const sidebar = document.getElementById('sidebar'); | |
| const overlay = document.querySelector('.overlay'); | |
| sidebar.classList.toggle('active'); | |
| overlay.classList.toggle('active'); | |
| } | |
| function switchTab(tabName) { | |
| // Remove active class from all nav items | |
| document.querySelectorAll('.nav-item').forEach(item => item.classList.remove('active')); | |
| // Add active class to clicked (this is a simulation) | |
| event.currentTarget.classList.add('active'); | |
| // Visual feedback for switching tabs | |
| document.querySelector('.page-title').innerText = tabName.charAt(0).toUpperCase() + tabName.slice(1); | |
| if(window.innerWidth < 992) { | |
| toggleSidebar(); | |
| } | |
| } | |
| function setTradeType(type) { | |
| currentTradeType = type; | |
| const tabs = document.querySelectorAll('.trade-tab'); | |
| const btn = document.getElementById('submit-btn'); | |
| const priceInput = document.getElementById('trade-price'); | |
| tabs.forEach(t => t.classList.remove('active')); | |
| if(type === 'buy') { | |
| tabs[0].classList.add('active'); | |
| btn.style.backgroundColor = 'var(--success)'; | |
| btn.innerText = `Buy BTC`; | |
| priceInput.style.borderColor = 'var(--border)'; | |
| } else { | |
| tabs[1].classList.add('active'); | |
| btn.style.backgroundColor = 'var(--danger)'; | |
| btn.innerText = `Sell BTC`; | |
| } | |
| } | |
| function calculateTotal() { | |
| const amount = parseFloat(document.getElementById('trade-amount').value) || 0; | |
| const price = 64230.50; // Fixed for demo | |
| const total = amount * price; | |
| document.getElementById('trade-total').value = '$' + total.toLocaleString(undefined, {minimumFractionDigits: 2, maximumFractionDigits: 2}); | |
| } | |
| function executeTrade(e) { | |
| e.preventDefault(); | |
| const amount = document.getElementById('trade-amount').value; | |
| if(!amount || amount <= 0) { | |
| alert("Please enter a valid amount"); | |
| return; | |
| } | |
| const type = currentTradeType === 'buy' ? 'Purchased' : 'Sold'; | |
| alert(`${type} ${amount} BTC successfully!`); | |
| // Reset form | |
| document.getElementById('trade-amount').value = ''; | |
| document.getElementById('trade-total').value = ''; | |
| } | |
| function renderTables() { | |
| // Render Holdings | |
| const holdingsBody = document.getElementById('holdings-table'); | |
| holdingsBody.innerHTML = ''; | |
| portfolioData.holdings.forEach(coin => { | |
| const row = document.createElement('tr'); | |
| const pnlClass = coin.pnl >= 0 ? 'positive' : 'negative'; | |
| const pnlIcon = coin.pnl >= 0 ? 'fa-caret-up' : 'fa-caret-down'; | |
| row.innerHTML = ` | |
| <td> | |
| <div class="coin-cell"> | |
| <div class="coin-icon-sm" style="background: linear-gradient(45deg, #FF9966, #FF5E62)">${coin.symbol[0]}</div> | |
| <div> | |
| <div style="font-weight: 600">${coin.symbol}</div> | |
| <div style="font-size: 11px; color: var(--text-secondary)">${coin.name}</div> | |
| </div> | |
| </div> | |
| </td> | |
| <td>$${coin.price.toLocaleString()}</td> | |
| <td>$${(coin.price * coin.amount).toLocaleString()}</td> | |
| <td class="${pnlClass}"> | |
| <i class="fas ${pnlIcon}"></i> ${Math.abs(coin.pnl)}% | |
| </td> | |
| `; | |
| holdingsBody.appendChild(row); | |
| }); | |
| // Render Watchlist | |
| const watchlistBody = document.getElementById('watchlist-table'); | |
| watchlistBody.innerHTML = ''; | |
| portfolioData.watchlist.forEach(stock => { | |
| const row = document.createElement('tr'); | |
| const changeClass = stock.change >= 0 ? 'positive' : 'negative'; | |
| const changeIcon = stock.change >= 0 ? 'fa-caret-up' : 'fa-caret-down'; | |
| row.innerHTML = ` | |
| <td> | |
| <div class="coin-cell"> | |
| <div class="coin-icon-sm" style="background: #2d3436">${stock.symbol[0]}</div> | |
| <div> | |
| <div style="font-weight: 600">${stock.symbol}</div> | |
| <div style="font-size: 11px; color: var(--text-secondary)">${stock.name}</div> | |
| </div> | |
| </div> | |
| </td> | |
| <td>$${stock.price.toLocaleString()}</td> | |
| <td class="${changeClass}"> | |
| <i class="fas ${changeIcon}"></i> ${stock.change}% | |
| </td> | |
| `; | |
| watchlistBody.appendChild(row); | |
| }); | |
| } | |
| function initChart() { | |
| const ctx = document.getElementById('portfolioChart').getContext('2d'); | |
| // Gradient for chart | |
| const gradient = ctx.createLinearGradient(0, 0, 0, 400); | |
| gradient.addColorStop(0, 'rgba(41, 98, 255, 0.5)'); | |
| gradient.addColorStop(1, 'rgba(41, 98, 255, 0.0)'); | |
| const labels = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']; | |
| // Simulated data points | |
| const dataPoints = [60000, 62000, 59000, 65000, 70000, 68000, 75000, 80000, 78000, 85000, 90000, 124500]; | |
| chartInstance = new Chart(ctx, { | |
| type: 'line', | |
| data: { | |
| labels: labels, | |
| datasets: [{ | |
| label: 'Portfolio Value', | |
| data: dataPoints, | |
| borderColor: '#2962ff', | |
| backgroundColor: gradient, | |
| borderWidth: 2, | |
| pointBackgroundColor: '#2962ff', | |
| pointBorderColor: '#fff', | |
| pointHoverBackgroundColor: '#fff', | |
| pointHoverBorderColor: '#2962ff', | |
| fill: true, | |
| tension: 0.4 | |
| }] | |
| }, | |
| options: { | |
| responsive: true, | |
| maintainAspectRatio: false, | |
| plugins: { | |
| legend: { | |
| display: false | |
| }, | |
| tooltip: { | |
| mode: 'index', | |
| intersect: false, | |
| backgroundColor: '#181b21', | |
| titleColor: '#fff', | |
| bodyColor: '#8b949e', | |
| borderColor: '#2f3336', | |
| borderWidth: 1, | |
| callbacks: { | |
| label: function(context) { | |
| return '$' + context.parsed.y.toLocaleString(); | |
| } | |
| } | |
| } | |
| }, | |
| scales: { | |
| x: { | |
| grid: { | |
| color: '#2f3336', | |
| drawBorder: false | |
| }, | |
| ticks: { | |
| color: '#8b949e' | |
| } | |
| }, | |
| y: { | |
| grid: { | |
| color: '#2f3336', | |
| drawBorder: false | |
| }, | |
| ticks: { | |
| color: '#8b949e', | |
| callback: function(value) { | |
| return '$' + value / 1000 + 'k'; | |
| } | |
| } | |
| } | |
| }, | |
| interaction: { | |
| mode: 'nearest', | |
| axis: 'x', | |
| intersect: false | |
| } | |
| } | |
| }); | |
| } | |
| function updateLiveData() { | |
| setInterval(() => { | |
| // Simulate slight fluctuation in balance | |
| const fluctuation = (Math.random() - 0.5) * 100; | |
| let currentBalance = parseFloat(document.getElementById('total-balance').innerText.replace(/[^0-9.-]+/g,"")); | |
| currentBalance += fluctuation; | |
| document.getElementById('total-balance').innerText = '$' + currentBalance.toLocaleString(undefined, {minimumFractionDigits: 2, maximumFractionDigits: 2}); | |
| // Flash effect on update | |
| const balanceEl = document.getElementById('total-balance'); | |
| balanceEl.style.transition = 'color 0.3s'; | |
| balanceEl.style.color = fluctuation > 0 ? 'var(--success)' : 'var(--danger)'; | |
| setTimeout(() => { | |
| balanceEl.style.color = 'var(--text-primary)'; | |
| }, 500); | |
| }, 3000); | |
| } | |
| </script> | |
| </body> | |
| </html> |