Spaces:
Running
Running
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>FinWise โ Dashboard</title> | |
| <link rel="stylesheet" href="shared.css"> | |
| <script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.0/dist/chart.umd.min.js"></script> | |
| <style> | |
| .hero-banner { | |
| background: linear-gradient(135deg, rgba(34,211,238,0.08) 0%, rgba(16,185,129,0.05) 100%); | |
| border: 1px solid var(--border2); | |
| border-radius: var(--r-lg); | |
| padding: 28px 32px; | |
| margin-bottom: 24px; | |
| display: flex; | |
| align-items: center; | |
| justify-content: space-between; | |
| gap: 20px; | |
| position: relative; | |
| overflow: hidden; | |
| } | |
| .hero-banner::before { | |
| content: ''; | |
| position: absolute; | |
| top: -40px; right: -40px; | |
| width: 200px; height: 200px; | |
| border-radius: 50%; | |
| background: radial-gradient(circle, rgba(34,211,238,0.12) 0%, transparent 70%); | |
| pointer-events: none; | |
| } | |
| .hero-greeting { font-family: var(--font-head); font-size: 13px; color: var(--text2); text-transform: uppercase; letter-spacing: 0.1em; } | |
| .hero-amount { font-family: var(--font-head); font-size: 42px; font-weight: 800; line-height: 1; margin: 8px 0; } | |
| .hero-sub { font-size: 14px; color: var(--text2); } | |
| .hero-actions { display: flex; gap: 12px; flex-wrap: wrap; } | |
| .portfolio-value-change { display: flex; align-items: center; gap: 8px; margin-top: 6px; } | |
| .quick-actions { | |
| display: grid; | |
| grid-template-columns: repeat(4, 1fr); | |
| gap: 12px; | |
| margin-bottom: 24px; | |
| } | |
| .quick-action-card { | |
| background: var(--card); | |
| border: 1px solid var(--border); | |
| border-radius: var(--r); | |
| padding: 18px; | |
| text-align: center; | |
| cursor: pointer; | |
| text-decoration: none; | |
| transition: all var(--transition); | |
| display: block; | |
| } | |
| .quick-action-card:hover { | |
| border-color: var(--border2); | |
| transform: translateY(-3px); | |
| box-shadow: var(--glow-c); | |
| } | |
| .qa-icon { font-size: 28px; margin-bottom: 8px; } | |
| .qa-label { font-size: 12px; font-weight: 700; color: var(--text2); text-transform: uppercase; letter-spacing: 0.06em; } | |
| .chart-card { height: 100%; } | |
| .chart-container { position: relative; height: 240px; } | |
| .goal-item { | |
| margin-bottom: 16px; | |
| } | |
| .goal-header { | |
| display: flex; | |
| justify-content: space-between; | |
| margin-bottom: 6px; | |
| font-size: 13px; | |
| } | |
| .goal-name { font-weight: 600; } | |
| .goal-pct { color: var(--cyan); font-family: var(--font-mono); } | |
| .activity-item { | |
| display: flex; | |
| align-items: center; | |
| gap: 14px; | |
| padding: 12px 0; | |
| border-bottom: 1px solid rgba(34,211,238,0.05); | |
| } | |
| .activity-item:last-child { border-bottom: none; } | |
| .activity-icon { | |
| width: 38px; height: 38px; | |
| border-radius: 10px; | |
| display: flex; align-items: center; justify-content: center; | |
| font-size: 16px; | |
| flex-shrink: 0; | |
| } | |
| .activity-info { flex: 1; } | |
| .activity-name { font-weight: 600; font-size: 14px; } | |
| .activity-date { font-size: 12px; color: var(--text2); margin-top: 2px; } | |
| .activity-amount { font-family: var(--font-mono); font-size: 14px; font-weight: 600; } | |
| .market-overview { | |
| display: grid; | |
| grid-template-columns: repeat(auto-fit, minmax(130px, 1fr)); | |
| gap: 10px; | |
| } | |
| .market-item { | |
| background: var(--bg3); | |
| border-radius: var(--r-sm); | |
| padding: 12px; | |
| text-align: center; | |
| } | |
| .market-sym { font-size: 11px; font-weight: 700; color: var(--text2); margin-bottom: 4px; } | |
| .market-val { font-family: var(--font-mono); font-size: 14px; font-weight: 600; } | |
| .market-chg { font-size: 11px; margin-top: 2px; font-weight: 600; } | |
| .allocation-legend { margin-top: 12px; } | |
| .legend-item { | |
| display: flex; align-items: center; gap: 10px; | |
| padding: 6px 0; | |
| font-size: 13px; | |
| } | |
| .legend-dot { width: 10px; height: 10px; border-radius: 50%; flex-shrink: 0; } | |
| .legend-name { flex: 1; color: var(--text2); } | |
| .legend-pct { font-family: var(--font-mono); font-size: 12px; color: var(--text); font-weight: 600; } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="app-shell"> | |
| <!-- Sidebar --> | |
| <nav class="sidebar"> | |
| <div class="sidebar-logo"> | |
| <div class="logo-mark"> | |
| <div class="logo-icon">๐</div> | |
| <div> | |
| <div class="logo-text">FinWise</div> | |
| <div class="logo-sub">Smart Investing</div> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="nav-section"> | |
| <div class="nav-label">Main</div> | |
| <a href="index.html" class="nav-item"><span class="nav-icon">๐ </span> Dashboard</a> | |
| <a href="portfolio.html" class="nav-item"><span class="nav-icon">๐</span> Portfolio Builder</a> | |
| <a href="risk.html" class="nav-item"><span class="nav-icon">๐ฏ</span> Risk Analyzer</a> | |
| <a href="tracker.html" class="nav-item"><span class="nav-icon">๐</span> Tracker</a> | |
| <div class="nav-label">Tools</div> | |
| <a href="calculators.html" class="nav-item"><span class="nav-icon">๐งฎ</span> Calculators</a> | |
| <a href="insights.html" class="nav-item"><span class="nav-icon">๐ก</span> Insights <span class="nav-badge">New</span></a> | |
| </div> | |
| <div class="sidebar-footer"> | |
| <div class="market-ticker">Live Market</div> | |
| <div id="sidebar-tickers"></div> | |
| </div> | |
| </nav> | |
| <!-- Main --> | |
| <main class="main-content"> | |
| <!-- Hero Banner --> | |
| <div class="hero-banner fade-in"> | |
| <div> | |
| <div class="hero-greeting">๐ Good morning, Investor</div> | |
| <div class="hero-amount" id="hero-amount">$0.00</div> | |
| <div class="portfolio-value-change"> | |
| <span class="badge badge-emerald" id="hero-badge">โฒ +$0.00 today</span> | |
| <span class="text-muted text-sm">Total portfolio value</span> | |
| </div> | |
| <div class="hero-sub" style="margin-top:10px;">Your portfolio is performing <strong style="color:var(--cyan)">above average</strong> this month ๐</div> | |
| </div> | |
| <div class="hero-actions"> | |
| <a href="portfolio.html" class="btn btn-primary">๐ง Build Portfolio</a> | |
| <a href="tracker.html" class="btn btn-secondary">๐ View Tracker</a> | |
| </div> | |
| </div> | |
| <!-- Stat Grid --> | |
| <div class="stat-grid fade-in fade-in-1"> | |
| <div class="stat-card" style="--accent-color: var(--cyan)"> | |
| <div class="stat-label">Total Invested</div> | |
| <div class="stat-value" id="stat-invested">$0</div> | |
| <div class="stat-change up">๐ Since inception</div> | |
| </div> | |
| <div class="stat-card" style="--accent-color: var(--emerald)"> | |
| <div class="stat-label">Total Gain/Loss</div> | |
| <div class="stat-value up" id="stat-gain">+$0</div> | |
| <div class="stat-change up" id="stat-gain-pct">โฒ 0.00%</div> | |
| </div> | |
| <div class="stat-card" style="--accent-color: var(--violet)"> | |
| <div class="stat-label">Risk Score</div> | |
| <div class="stat-value" id="stat-risk">โ</div> | |
| <div class="stat-change" id="stat-risk-label">Moderate</div> | |
| </div> | |
| <div class="stat-card" style="--accent-color: var(--amber)"> | |
| <div class="stat-label">Diversification</div> | |
| <div class="stat-value" id="stat-div">โ</div> | |
| <div class="stat-change up">โฒ Well balanced</div> | |
| </div> | |
| </div> | |
| <!-- Quick Actions --> | |
| <div class="quick-actions fade-in fade-in-2"> | |
| <a href="portfolio.html" class="quick-action-card"><div class="qa-icon">๐๏ธ</div><div class="qa-label">Build Portfolio</div></a> | |
| <a href="risk.html" class="quick-action-card"><div class="qa-icon">๐ฏ</div><div class="qa-label">Risk Check</div></a> | |
| <a href="calculators.html" class="quick-action-card"><div class="qa-icon">๐งฎ</div><div class="qa-label">Calculators</div></a> | |
| <a href="insights.html" class="quick-action-card"><div class="qa-icon">๐ก</div><div class="qa-label">AI Insights</div></a> | |
| </div> | |
| <!-- Charts Row --> | |
| <div class="grid-60-40 fade-in fade-in-3" style="margin-bottom:20px"> | |
| <div class="card chart-card"> | |
| <div class="card-title">๐ Portfolio Performance <span class="badge badge-emerald" style="margin-left:auto">+12.4% YTD</span></div> | |
| <div class="chart-container"> | |
| <canvas id="performanceChart"></canvas> | |
| </div> | |
| </div> | |
| <div class="card"> | |
| <div class="card-title">๐ฅง Allocation</div> | |
| <div style="position:relative;height:180px"> | |
| <canvas id="allocChart"></canvas> | |
| </div> | |
| <div class="allocation-legend" id="alloc-legend"></div> | |
| </div> | |
| </div> | |
| <!-- Bottom Row --> | |
| <div class="grid-2 fade-in fade-in-4"> | |
| <!-- Goals --> | |
| <div class="card"> | |
| <div class="card-title">๐ฏ Goal Progress</div> | |
| <div id="goals-list"> | |
| <div class="goal-item"> | |
| <div class="goal-header"><span class="goal-name">๐๏ธ Retirement Fund</span><span class="goal-pct">34%</span></div> | |
| <div class="progress-bar"><div class="progress-fill" style="width:34%;background:linear-gradient(90deg,var(--cyan),var(--emerald))"></div></div> | |
| <div class="text-sm text-muted" style="margin-top:4px">$34,000 / $100,000 target by 2045</div> | |
| </div> | |
| <div class="goal-item"> | |
| <div class="goal-header"><span class="goal-name">๐ Down Payment</span><span class="goal-pct">61%</span></div> | |
| <div class="progress-bar"><div class="progress-fill" style="width:61%;background:linear-gradient(90deg,var(--violet),var(--cyan))"></div></div> | |
| <div class="text-sm text-muted" style="margin-top:4px">$30,500 / $50,000 target by 2027</div> | |
| </div> | |
| <div class="goal-item"> | |
| <div class="goal-header"><span class="goal-name">๐ Education Fund</span><span class="goal-pct">18%</span></div> | |
| <div class="progress-bar"><div class="progress-fill" style="width:18%;background:linear-gradient(90deg,var(--amber),var(--rose))"></div></div> | |
| <div class="text-sm text-muted" style="margin-top:4px">$3,600 / $20,000 target by 2030</div> | |
| </div> | |
| </div> | |
| <a href="calculators.html" class="btn btn-secondary btn-sm btn-full" style="margin-top:16px">Plan a new goal โ</a> | |
| </div> | |
| <!-- Recent Activity --> | |
| <div class="card"> | |
| <div class="card-title">โก Recent Activity</div> | |
| <div id="activity-list"> | |
| <div class="activity-item"> | |
| <div class="activity-icon" style="background:rgba(16,185,129,0.15)">๐ฐ</div> | |
| <div class="activity-info"><div class="activity-name">Bought VOO</div><div class="activity-date">May 1, 2026</div></div> | |
| <div class="activity-amount up">+3 shares</div> | |
| </div> | |
| <div class="activity-item"> | |
| <div class="activity-icon" style="background:rgba(34,211,238,0.15)">๐ฅ</div> | |
| <div class="activity-info"><div class="activity-name">Dividend โ AAPL</div><div class="activity-date">Apr 28, 2026</div></div> | |
| <div class="activity-amount up">+$12.40</div> | |
| </div> | |
| <div class="activity-item"> | |
| <div class="activity-icon" style="background:rgba(139,92,246,0.15)">๐</div> | |
| <div class="activity-info"><div class="activity-name">Rebalanced Portfolio</div><div class="activity-date">Apr 20, 2026</div></div> | |
| <div class="activity-amount" style="color:var(--text2)">Optimized</div> | |
| </div> | |
| <div class="activity-item"> | |
| <div class="activity-icon" style="background:rgba(245,158,11,0.15)">๐น</div> | |
| <div class="activity-info"><div class="activity-name">Added NVDA</div><div class="activity-date">Apr 15, 2026</div></div> | |
| <div class="activity-amount up">+1 share</div> | |
| </div> | |
| </div> | |
| <a href="tracker.html" class="btn btn-secondary btn-sm btn-full" style="margin-top:16px">Full history โ</a> | |
| </div> | |
| </div> | |
| <!-- Market Overview --> | |
| <div class="card fade-in" style="margin-top:20px"> | |
| <div class="card-title">๐ Market Overview</div> | |
| <div class="market-overview"> | |
| <div class="market-item"><div class="market-sym">S&P 500</div><div class="market-val">5,308</div><div class="market-chg up">โฒ +0.26%</div></div> | |
| <div class="market-item"><div class="market-sym">NASDAQ</div><div class="market-val">16,742</div><div class="market-chg down">โผ -0.46%</div></div> | |
| <div class="market-item"><div class="market-sym">DOW</div><div class="market-val">39,512</div><div class="market-chg up">โฒ +0.18%</div></div> | |
| <div class="market-item"><div class="market-sym">BTC</div><div class="market-val">$68,420</div><div class="market-chg up">โฒ +2.14%</div></div> | |
| <div class="market-item"><div class="market-sym">GOLD</div><div class="market-val">$2,318</div><div class="market-chg up">โฒ +1.49%</div></div> | |
| <div class="market-item"><div class="market-sym">10Y BOND</div><div class="market-val">4.48%</div><div class="market-chg down">โผ -0.03%</div></div> | |
| <div class="market-item"><div class="market-sym">USD/EUR</div><div class="market-val">0.924</div><div class="market-chg down">โผ -0.12%</div></div> | |
| <div class="market-item"><div class="market-sym">VIX</div><div class="market-val">14.82</div><div class="market-chg up">โฒ +3.2%</div></div> | |
| </div> | |
| </div> | |
| </main> | |
| </div> | |
| <!-- Mobile Bottom Nav --> | |
| <nav class="bottom-nav"> | |
| <div class="bottom-nav-inner"> | |
| <a href="index.html" class="bottom-nav-item"><span class="bnav-icon">๐ </span>Home</a> | |
| <a href="portfolio.html" class="bottom-nav-item"><span class="bnav-icon">๐</span>Portfolio</a> | |
| <a href="risk.html" class="bottom-nav-item"><span class="bnav-icon">๐ฏ</span>Risk</a> | |
| <a href="tracker.html" class="bottom-nav-item"><span class="bnav-icon">๐</span>Track</a> | |
| <a href="calculators.html" class="bottom-nav-item"><span class="bnav-icon">๐งฎ</span>Calc</a> | |
| <a href="insights.html" class="bottom-nav-item"><span class="bnav-icon">๐ก</span>Insights</a> | |
| </div> | |
| </nav> | |
| <script src="shared.js"></script> | |
| <script> | |
| document.addEventListener('DOMContentLoaded', () => { | |
| const portfolio = getPortfolio(); | |
| const currentValue = portfolio.assets.reduce((s,a) => s + a.shares * a.price, 0); | |
| const invested = portfolio.totalInvested; | |
| const gain = currentValue - invested; | |
| const gainPct = (gain / invested) * 100; | |
| const todayChange = currentValue * 0.0026; | |
| // Hero | |
| animateCounter(document.getElementById('hero-amount'), currentValue, '$'); | |
| document.getElementById('hero-badge').textContent = `โฒ +$${todayChange.toFixed(2)} today`; | |
| // Stats | |
| document.getElementById('stat-invested').textContent = fmtK(invested); | |
| const gainEl = document.getElementById('stat-gain'); | |
| gainEl.textContent = (gain >= 0 ? '+' : '') + fmt$(gain); | |
| gainEl.className = 'stat-value ' + (gain >= 0 ? 'up' : 'down'); | |
| document.getElementById('stat-gain-pct').textContent = (gainPct >= 0 ? 'โฒ +' : 'โผ ') + gainPct.toFixed(2) + '%'; | |
| document.getElementById('stat-gain-pct').className = 'stat-change ' + (gain >= 0 ? 'up' : 'down'); | |
| const riskScore = calcRiskScore(portfolio); | |
| const divScore = calcDiversification(portfolio); | |
| document.getElementById('stat-risk').textContent = riskScore + '/100'; | |
| const riskLabels = ['Very Low','Low','Moderate','Moderate-High','High']; | |
| const riskLabel = riskLabels[Math.floor(riskScore / 25)]; | |
| document.getElementById('stat-risk-label').textContent = 'โ ' + riskLabel; | |
| document.getElementById('stat-div').textContent = divScore + '/100'; | |
| // Performance Chart | |
| const history = generateHistory(90, invested * 0.88); | |
| const perfCtx = document.getElementById('performanceChart').getContext('2d'); | |
| const grad = perfCtx.createLinearGradient(0, 0, 0, 240); | |
| grad.addColorStop(0, 'rgba(34,211,238,0.25)'); | |
| grad.addColorStop(1, 'rgba(34,211,238,0)'); | |
| new Chart(perfCtx, { | |
| type: 'line', | |
| data: { | |
| labels: history.filter((_,i) => i % 6 === 0).map(d => d.date), | |
| datasets: [{ | |
| label: 'Portfolio Value', | |
| data: history.filter((_,i) => i % 6 === 0).map(d => d.value), | |
| borderColor: '#22d3ee', | |
| backgroundColor: grad, | |
| borderWidth: 2.5, | |
| fill: true, | |
| tension: 0.45, | |
| pointRadius: 0, | |
| pointHoverRadius: 5, | |
| pointHoverBackgroundColor: '#22d3ee', | |
| }] | |
| }, | |
| options: { | |
| responsive: true, maintainAspectRatio: false, | |
| plugins: { legend: { display: false }, tooltip: { | |
| callbacks: { label: ctx => ' $' + ctx.raw.toLocaleString('en-US', {maximumFractionDigits:0}) } | |
| }}, | |
| scales: { | |
| x: { grid: { display: false }, ticks: { maxTicksLimit: 6, font: { size: 11 } } }, | |
| y: { grid: { color: 'rgba(34,211,238,0.06)' }, ticks: { | |
| callback: v => '$' + (v/1000).toFixed(0) + 'K', font: { size: 11 } | |
| }} | |
| }, | |
| interaction: { intersect: false, mode: 'index' } | |
| } | |
| }); | |
| // Allocation Donut | |
| const allocCtx = document.getElementById('allocChart').getContext('2d'); | |
| new Chart(allocCtx, { | |
| type: 'doughnut', | |
| data: { | |
| labels: portfolio.assets.map(a => a.ticker), | |
| datasets: [{ | |
| data: portfolio.assets.map(a => a.pct), | |
| backgroundColor: portfolio.assets.map(a => a.color), | |
| borderColor: 'rgba(5,13,26,0.8)', | |
| borderWidth: 3, | |
| hoverOffset: 8 | |
| }] | |
| }, | |
| options: { | |
| responsive: true, maintainAspectRatio: false, | |
| cutout: '70%', | |
| plugins: { legend: { display: false } } | |
| } | |
| }); | |
| // Legend | |
| const legendEl = document.getElementById('alloc-legend'); | |
| legendEl.innerHTML = portfolio.assets.slice(0,5).map(a => ` | |
| <div class="legend-item"> | |
| <div class="legend-dot" style="background:${a.color}"></div> | |
| <span class="legend-name">${a.ticker}</span> | |
| <span class="legend-pct">${a.pct}%</span> | |
| </div> | |
| `).join('') + (portfolio.assets.length > 5 ? `<div class="legend-item"><span class="legend-name text-muted">+ ${portfolio.assets.length-5} more</span></div>` : ''); | |
| }); | |
| </script> | |
| </body> | |
| </html> | |