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(5, 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); | |
| } | |
| /* Picks card highlight */ | |
| .quick-action-card.picks-card { | |
| border-color: rgba(16,185,129,0.35); | |
| background: rgba(16,185,129,0.04); | |
| } | |
| .quick-action-card.picks-card:hover { | |
| border-color: var(--emerald); | |
| box-shadow: 0 0 18px rgba(16,185,129,0.18); | |
| } | |
| .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; } | |
| .qa-badge-pill { | |
| display: inline-block; | |
| margin-top: 5px; | |
| background: var(--emerald); | |
| color: #000; | |
| font-size: 9px; | |
| font-weight: 800; | |
| padding: 2px 7px; | |
| border-radius: 20px; | |
| text-transform: uppercase; | |
| letter-spacing: .5px; | |
| } | |
| .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; } | |
| /* Picks CTA banner */ | |
| .picks-cta { | |
| background: linear-gradient(135deg, rgba(16,185,129,0.1), rgba(34,211,238,0.06)); | |
| border: 1px solid rgba(16,185,129,0.4); | |
| border-radius: var(--r-lg); | |
| padding: 22px 28px; | |
| display: flex; | |
| align-items: center; | |
| justify-content: space-between; | |
| gap: 16px; | |
| flex-wrap: wrap; | |
| margin-top: 20px; | |
| } | |
| .picks-cta-title { font-size: 15px; font-weight: 800; margin-bottom: 5px; } | |
| .picks-cta-sub { font-size: 13px; color: var(--text2); } | |
| @media (max-width: 768px) { | |
| .quick-actions { grid-template-columns: repeat(3, 1fr); } | |
| .picks-cta { flex-direction: column; align-items: flex-start; } | |
| } | |
| @media (max-width: 480px) { | |
| .quick-actions { grid-template-columns: repeat(2, 1fr); } | |
| } | |
| </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 active"><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> | |
| <!-- ✅ NEW: Stock & Option Picks --> | |
| <a href="picks.html" class="nav-item"><span class="nav-icon">🏹</span> Stock & Option Picks <span class="nav-badge" style="background:var(--emerald);color:#000">New</span></a> | |
| <!-- ✅ NEW: Dividend Harvesting --> | |
| <a href="dividends.html" class="nav-item"><span class="nav-icon">💰</span> Dividend Harvesting <span class="nav-badge" style="background:var(--gold,#fbbf24);color:#000">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 — now 5 cols with Picks --> | |
| <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> | |
| <!-- ✅ NEW --> | |
| <a href="picks.html" class="quick-action-card picks-card"> | |
| <div class="qa-icon">🏹</div> | |
| <div class="qa-label">Picks</div> | |
| <div class="qa-badge-pill">47 Live</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> | |
| <!-- ✅ NEW: Picks CTA Banner --> | |
| <div class="picks-cta fade-in"> | |
| <div> | |
| <div class="picks-cta-title">🏹 Stock & Option Picks — Now Live</div> | |
| <div class="picks-cta-sub">47 curated picks across momentum stocks, option selling strategies (CSP, Covered Calls, Strangles, Iron Condors), LEAP calls, and 3× leveraged ETFs. Full filters, sparklines & live refresh.</div> | |
| </div> | |
| <a href="picks.html" class="btn btn-primary" style="white-space:nowrap;flex-shrink:0">Explore Picks →</a> | |
| </div> | |
| <!-- ✅ NEW: Dividend Harvesting CTA Banner --> | |
| <div class="picks-cta fade-in" style="background:linear-gradient(135deg,rgba(251,191,36,.1),rgba(16,185,129,.06));border-color:rgba(251,191,36,.4);margin-top:12px"> | |
| <div> | |
| <div class="picks-cta-title">💰 Dividend Harvesting — Track Upcoming Payouts</div> | |
| <div class="picks-cta-sub">Find stocks paying dividends in the next 6–8 weeks. Filter by yield, sector, frequency and ex-div date. Includes payout history, consistency scores and CSV export.</div> | |
| </div> | |
| <a href="dividends.html" class="btn btn-primary" style="white-space:nowrap;flex-shrink:0;background:#fbbf24;color:#000">Explore Dividends →</a> | |
| </div> | |
| </main> | |
| </div> | |
| <!-- ══════════ MOBILE BOTTOM NAV ══════════ --> | |
| <nav class="bottom-nav"> | |
| <div class="bottom-nav-inner"> | |
| <a href="index.html" class="bottom-nav-item active"><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="picks.html" class="bottom-nav-item"><span class="bnav-icon">🏹</span>Picks</a> | |
| <!-- ✅ NEW --> | |
| <a href="dividends.html" class="bottom-nav-item"><span class="bnav-icon">💰</span>Divs</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']; | |
| document.getElementById('stat-risk-label').textContent = '→ ' + riskLabels[Math.floor(riskScore / 25)]; | |
| 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> | |