Spaces:
Running
Running
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>FundTrack Pro | Mutual Fund Intelligence</title> | |
| <!-- Google Fonts --> | |
| <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet"> | |
| <!-- Font Awesome for Icons --> | |
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> | |
| <!-- Chart.js for Performance and Sector Analysis --> | |
| <script src="https://cdn.jsdelivr.net/npm/chart.js"></script> | |
| <style> | |
| :root { | |
| --primary: #2563eb; | |
| --primary-dark: #1d4ed8; | |
| --secondary: #64748b; | |
| --success: #10b981; | |
| --danger: #ef4444; | |
| --warning: #f59e0b; | |
| --background: #f8fafc; | |
| --surface: #ffffff; | |
| --text-main: #1e293b; | |
| --text-muted: #64748b; | |
| --border: #e2e8f0; | |
| --shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1); | |
| --glass: rgba(255, 255, 255, 0.7); | |
| } | |
| * { | |
| box-sizing: border-box; | |
| margin: 0; | |
| padding: 0; | |
| font-family: 'Inter', sans-serif; | |
| } | |
| body { | |
| background-color: var(--background); | |
| color: var(--text-main); | |
| display: flex; | |
| min-height: 100vh; | |
| overflow-x: hidden; | |
| } | |
| /* --- Sidebar Navigation --- */ | |
| nav { | |
| width: 260px; | |
| background: #0f172a; | |
| color: white; | |
| display: flex; | |
| flex-direction: column; | |
| position: fixed; | |
| height: 100vh; | |
| transition: all 0.3s ease; | |
| z-index: 100; | |
| } | |
| .nav-header { | |
| padding: 2rem 1.5rem; | |
| font-size: 1.5rem; | |
| font-weight: 700; | |
| display: flex; | |
| align-items: center; | |
| gap: 10px; | |
| color: #fff; | |
| } | |
| .nav-header i { | |
| color: var(--primary); | |
| } | |
| .nav-links { | |
| flex: 1; | |
| padding: 0 1rem; | |
| } | |
| .nav-item { | |
| padding: 12px 16px; | |
| margin-bottom: 8px; | |
| border-radius: 8px; | |
| cursor: pointer; | |
| display: flex; | |
| align-items: center; | |
| gap: 12px; | |
| transition: all 0.2s; | |
| color: #94a3b8; | |
| text-decoration: none; | |
| font-weight: 500; | |
| } | |
| .nav-item:hover, .nav-item.active { | |
| background: rgba(255, 255, 255, 0.1); | |
| color: white; | |
| } | |
| .nav-item.active { | |
| background: var(--primary); | |
| color: white; | |
| } | |
| /* --- Main Content Area --- */ | |
| main { | |
| margin-left: 260px; | |
| flex: 1; | |
| padding: 2rem; | |
| width: calc(100% - 260px); | |
| } | |
| header { | |
| display: flex; | |
| justify-content: space-between; | |
| align-items: center; | |
| margin-bottom: 2rem; | |
| background: var(--glass); | |
| backdrop-filter: blur(10px); | |
| padding: 1rem 2rem; | |
| border-radius: 16px; | |
| border: 1px solid var(--border); | |
| position: sticky; | |
| top: 0; | |
| z-index: 90; | |
| } | |
| .anycoder-link { | |
| font-size: 0.85rem; | |
| color: var(--primary); | |
| text-decoration: none; | |
| font-weight: 600; | |
| transition: opacity 0.2s; | |
| } | |
| .anycoder-link:hover { | |
| opacity: 0.8; | |
| } | |
| .user-profile { | |
| display: flex; | |
| align-items: center; | |
| gap: 15px; | |
| } | |
| .notification-bell { | |
| position: relative; | |
| cursor: pointer; | |
| font-size: 1.2rem; | |
| color: var(--secondary); | |
| } | |
| .badge { | |
| position: absolute; | |
| top: -5px; | |
| right: -5px; | |
| background: var(--danger); | |
| color: white; | |
| font-size: 0.6rem; | |
| padding: 2px 5px; | |
| border-radius: 50%; | |
| } | |
| /* --- Dashboard Grid --- */ | |
| .dashboard-grid { | |
| display: grid; | |
| grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); | |
| gap: 1.5rem; | |
| margin-bottom: 2rem; | |
| } | |
| .card { | |
| background: var(--surface); | |
| padding: 1.5rem; | |
| border-radius: 16px; | |
| border: 1px solid var(--border); | |
| box-shadow: var(--shadow); | |
| transition: transform 0.2s; | |
| } | |
| .card:hover { | |
| transform: translateY(-4px); | |
| } | |
| .card-title { | |
| font-size: 1.1rem; | |
| font-weight: 600; | |
| margin-bottom: 1.5rem; | |
| display: flex; | |
| justify-content: space-between; | |
| align-items: center; | |
| } | |
| /* --- Specific Components --- */ | |
| .metric { | |
| font-size: 2rem; | |
| font-weight: 700; | |
| margin-bottom: 0.5rem; | |
| } | |
| .trend { | |
| font-size: 0.9rem; | |
| display: flex; | |
| align-items: center; | |
| gap: 5px; | |
| } | |
| .trend.up { color: var(--success); } | |
| .trend.down { color: var(--danger); } | |
| /* Tables */ | |
| .data-table-container { | |
| overflow-x: auto; | |
| margin-top: 1rem; | |
| } | |
| table { | |
| width: 100%; | |
| border-collapse: collapse; | |
| text-align: left; | |
| } | |
| th { | |
| padding: 12px; | |
| border-bottom: 2px solid var(--border); | |
| color: var(--text-muted); | |
| font-weight: 600; | |
| font-size: 0.85rem; | |
| text-transform: uppercase; | |
| } | |
| td { | |
| padding: 12px; | |
| border-bottom: 1px solid var(--border); | |
| font-size: 0.9rem; | |
| } | |
| .change-pill { | |
| padding: 4px 8px; | |
| border-radius: 6px; | |
| font-size: 0.75rem; | |
| font-weight: 600; | |
| } | |
| .pill-buy { background: #dcfce7; color: #166534; } | |
| .pill-sell { background: #fee2e2; color: #991b1b; } | |
| /* Alerts Section */ | |
| .alert-item { | |
| display: flex; | |
| gap: 15px; | |
| padding: 1rem; | |
| border-radius: 12px; | |
| margin-bottom: 1rem; | |
| border-left: 4px solid var(--primary); | |
| background: #f1f5f9; | |
| } | |
| .alert-item.critical { border-left-color: var(--danger); background: #fef2f2; } | |
| .alert-item.warning { border-left-color: var(--warning); background: #fffbeb; } | |
| .alert-content h4 { | |
| font-size: 0.95rem; | |
| margin-bottom: 4px; | |
| } | |
| .alert-content p { | |
| font-size: 0.85rem; | |
| color: var(--text-muted); | |
| } | |
| /* News Feed */ | |
| .news-grid { | |
| display: grid; | |
| grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); | |
| gap: 1.5rem; | |
| } | |
| .news-card { | |
| background: var(--surface); | |
| border-radius: 12px; | |
| overflow: hidden; | |
| border: 1px solid var(--border); | |
| cursor: pointer; | |
| transition: all 0.2s; | |
| } | |
| .news-card:hover { | |
| box-shadow: var(--shadow); | |
| } | |
| .news-img { | |
| width: 100%; | |
| height: 160px; | |
| background: #e2e8f0; | |
| object-fit: cover; | |
| } | |
| .news-body { | |
| padding: 1rem; | |
| } | |
| .news-tag { | |
| font-size: 0.7rem; | |
| text-transform: uppercase; | |
| color: var(--primary); | |
| font-weight: 700; | |
| margin-bottom: 8px; | |
| display: block; | |
| } | |
| .news-title { | |
| font-size: 0.95rem; | |
| font-weight: 600; | |
| line-height: 1.4; | |
| margin-bottom: 10px; | |
| } | |
| /* Performance Comparison Chart Area */ | |
| .chart-container { | |
| height: 300px; | |
| width: 100%; | |
| margin-top: 1rem; | |
| } | |
| /* Modal/Overlay for Fund Detail */ | |
| .overlay { | |
| position: fixed; | |
| top: 0; | |
| left: 0; | |
| width: 100%; | |
| height: 100%; | |
| background: rgba(0,0,0,0.5); | |
| display: none; | |
| justify-content: center; | |
| align-items: center; | |
| z-index: 1000; | |
| backdrop-filter: blur(4px); | |
| } | |
| .modal { | |
| background: var(--surface); | |
| width: 90%; | |
| max-width: 1000px; | |
| max-height: 90vh; | |
| border-radius: 20px; | |
| padding: 2rem; | |
| overflow-y: auto; | |
| position: relative; | |
| } | |
| .close-modal { | |
| position: absolute; | |
| top: 20px; | |
| right: 20px; | |
| cursor: pointer; | |
| font-size: 1.5rem; | |
| } | |
| /* Responsive Design */ | |
| @media (max-width: 1024px) { | |
| nav { width: 80px; } | |
| .nav-header span, .nav-item span { display: none; } | |
| main { margin-left: 80px; width: calc(100% - 80px); } | |
| } | |
| @media (max-width: 768px) { | |
| nav { display: none; } | |
| main { margin-left: 0; width: 100%; padding: 1rem; } | |
| header { flex-direction: column; gap: 1rem; text-align: center; } | |
| .dashboard-grid { grid-template-columns: 1fr; } | |
| } | |
| .hidden { display: none; } | |
| </style> | |
| </head> | |
| <body> | |
| <!-- Sidebar --> | |
| <nav> | |
| <div class="nav-header"> | |
| <i class="fa-solid fa-chart-line"></i> | |
| <span>FundTrack Pro</span> | |
| </div> | |
| <div class="nav-links"> | |
| <a href="#" class="nav-item active" onclick="showSection('dashboard')"> | |
| <i class="fa-solid fa-house"></i> <span>Dashboard</span> | |
| </a> | |
| <a href="#" class="nav-item" onclick="showSection('portfolio')"> | |
| <i class="fa-solid fa-wallet"></i> <span>Portfolio Analysis</span> | |
| </a> | |
| <a href="#" class="nav-item" onclick="showSection('alerts')"> | |
| <i class="fa-solid fa-bell"></i> <span>Alerts Center</span> | |
| </a> | |
| <a href="#" class="nav-item" onclick="showSection('news')"> | |
| <i class="fa-solid fa-newspaper"></i> <span>Market News</span> | |
| </a> | |
| </div> | |
| </nav> | |
| <!-- Main Content --> | |
| <main> | |
| <header> | |
| <div> | |
| <h2 id="section-title">Portfolio Overview</h2> | |
| <a href="https://huggingface.co/spaces/akhaliq/anycoder" class="anycoder-link" target="_blank">Built with anycoder</a> | |
| </div> | |
| <div class="user-profile"> | |
| <div class="notification-bell" onclick="showSection('alerts')"> | |
| <i class="fa-solid fa-bell"></i> | |
| <span class="badge" id="alert-count">3</span> | |
| </div> | |
| <div style="text-align: right"> | |
| <div style="font-weight: 600; font-size: 0.9rem;">Alex Investor</div> | |
| <div style="font-size: 0.75rem; color: var(--text-muted);">Premium Plan</div> | |
| </div> | |
| <img src="https://i.pravatar.cc/40" style="border-radius: 50%;" alt="User"> | |
| </div> | |
| </header> | |
| <!-- DASHBOARD SECTION --> | |
| <section id="dashboard"> | |
| <div class="dashboard-grid"> | |
| <div class="card"> | |
| <div class="card-title">Total Investment <i class="fa-solid fa-circle-info" style="font-size: 0.8rem; color: var(--text-muted);"></i></div> | |
| <div class="metric">$124,500</div> | |
| <div class="trend up"><i class="fa-solid fa-arrow-up"></i> 12.4% vs last year</div> | |
| </div> | |
| <div class="card"> | |
| <div class="card-title">Current Value <i class="fa-solid fa-circle-info" style="font-size: 0.8rem; color: var(--text-muted);"></i></div> | |
| <div class="metric">$142,100</div> | |
| <div class="trend up"><i class="fa-solid fa-arrow-up"></i> +$17,600 Unrealized</div> | |
| </div> | |
| <div class="card"> | |
| <div class="card-title">Active Funds <i class="fa-solid fa-circle-info" style="font-size: 0.8rem; color: var(--text-muted);"></i></div> | |
| <div class="metric">8</div> | |
| <div class="trend" style="color: var(--secondary);">Across 4 Categories</div> | |
| </div> | |
| </div> | |
| <div class="card" style="margin-bottom: 2rem;"> | |
| <div class="card-title">My Fund Performance vs Index</div> | |
| <div class="chart-container"> | |
| <canvas id="performanceChart"></canvas> | |
| </div> | |
| </div> | |
| <div class="card"> | |
| <div class="card-title">Quick Alerts</div> | |
| <div id="quick-alerts"> | |
| <!-- Alerts injected here --> | |
| </div> | |
| </div> | |
| </section> | |
| <!-- PORTFOLIO SECTION --> | |
| <section id="portfolio" class="hidden"> | |
| <div class="card"> | |
| <div class="card-title">Fund Detailed Analysis</div> | |
| <div class="data-table-container"> | |
| <table> | |
| <thead> | |
| <tr> | |
| <th>Fund Name</th> | |
| <th>Category</th> | |
| <th>Return (1Y)</th> | |
| <th>Benchmark</th> | |
| <th>Status</th> | |
| <th>Action</th> | |
| </tr> | |
| </thead> | |
| <tbody id="fund-table-body"> | |
| <!-- Funds injected here --> | |
| </tbody> | |
| </table> | |
| </div> | |
| </div> | |
| </section> | |
| <!-- ALERTS SECTION --> | |
| <section id="alerts" class="hidden"> | |
| <div style="max-width: 800px; margin: 0 auto;"> | |
| <h3 style="margin-bottom: 1.5rem;">System Notifications</h3> | |
| <div id="full-alerts-list"> | |
| <!-- Alerts injected here --> | |
| </div> | |
| </div> | |
| </section> | |
| <!-- NEWS SECTION --> | |
| <section id="news" class="hidden"> | |
| <div class="news-grid" id="news-container"> | |
| <!-- News cards injected here --> | |
| </div> | |
| </section> | |
| </main> | |
| <!-- Fund Detail Modal --> | |
| <div class="overlay" id="fund-modal"> | |
| <div class="modal"> | |
| <span class="close-modal" onclick="closeModal()">×</span> | |
| <div id="modal-content"> | |
| <!-- Dynamic Content --> | |
| </div> | |
| </div> | |
| </div> | |
| <script> | |
| /* --- MOCK DATA --- */ | |
| const FUNDS_DATA = [ | |
| { | |
| id: 1, | |
| name: "BlueChip Growth Fund", | |
| category: "Large Cap", | |
| objective: "Long term capital appreciation through large cap equities", | |
| manager: "Rajesh Kumar", | |
| performance: 18.5, | |
| benchmark: 14.2, | |
| index: 13.8, | |
| changes: { | |
| managerChanged: true, | |
| categoryChanged: false, | |
| objectiveChanged: false, | |
| managerOld: "Suresh Mehra" | |
| }, | |
| stocks: [ | |
| { name: "Reliance Ind", prev: 6.5, curr: 7.2, action: 'Buy' }, | |
| { name: "HDFC Bank", prev: 5.1, curr: 4.8, action: 'Sell' }, | |
| { name: "Infosys", prev: 3.2, curr: 4.1, action: 'Buy' }, | |
| { name: "TCS", prev: 4.0, curr: 3.5, action: 'Sell' }, | |
| ], | |
| sectors: [ | |
| { name: "Financials", prev: 25, curr: 28 }, | |
| { name: "IT", prev: 20, curr: 18 }, | |
| { name: "Energy", prev: 15, curr: 17 }, | |
| { name: "Consumer", prev: 10, curr: 12 }, | |
| ] | |
| }, | |
| { | |
| id: 2, | |
| name: "MidCap Alpha Fund", | |
| category: "Mid Cap", | |
| objective: "Aggressive growth in mid-sized companies", | |
| manager: "Anita Desai", | |
| performance: 24.1, | |
| benchmark: 19.5, | |
| index: 18.9, | |
| changes: { | |
| managerChanged: false, | |
| categoryChanged: true, | |
| objectiveChanged: true, | |
| categoryOld: "Multi Cap" | |
| }, | |
| stocks: [ | |
| { name: "Trent Ltd", prev: 2.1, curr: 3.5, action: 'Buy' }, | |
| { name: "Polycab", prev: 1.5, curr: 1.2, action: 'Sell' }, | |
| { name: "KEI Ind", prev: 0, curr: 1.8, action: 'Buy' }, | |
| ], | |
| sectors: [ | |
| { name: "Industrials", prev: 30, curr: 35 }, | |
| { name: "Healthcare", prev: 20, curr: 15 }, | |
| { name: "Chemicals", prev: 15, curr: 20 }, | |
| { name: "Others", prev: 35, curr: 30 }, | |
| ] | |
| }, | |
| { | |
| id: 3, | |
| name: "Global Tech Opportunity", | |
| category: "Thematic - Tech", | |
| objective: "Invest in global technology disruptors", | |
| manager: "Mark Sloan", | |
| performance: 12.2, | |
| benchmark: 15.1, | |
| index: 14.8, | |
| changes: { | |
| managerChanged: false, | |
| categoryChanged: false, | |
| objectiveChanged: false | |
| }, | |
| stocks: [ | |
| { name: "NVIDIA", prev: 8.1, curr: 10.5, action: 'Buy' }, | |
| { name: "Apple", prev: 12.0, curr: 11.2, action: 'Sell' }, | |
| { name: "Microsoft", prev: 9.5, curr: 9.8, action: 'Buy' }, | |
| ], | |
| sectors: [ | |
| { name: "Software", prev: 40, curr: 42 }, | |
| { name: "Hardware", prev: 30, curr: 28 }, | |
| { name: "AI Services", prev: 20, curr: 25 }, | |
| { name: "Cloud", prev: 10, curr: 5 }, | |
| ] | |
| } | |
| ]; | |
| const MOCK_NEWS = [ | |
| { fund: "BlueChip Growth Fund", title: "Market Shift: Large Caps showing resilience in Q3", source: "Economic Times", date: "2 hours ago", img: "https://picsum.photos/seed/news1/300/160" }, | |
| { fund: "MidCap Alpha Fund", title: "Midcap Sector Outlook: Why Industrials are booming", source: "MoneyControl", date: "5 hours ago", img: "https://picsum.photos/seed/news2/300/160" }, | |
| { fund: "Global Tech Opportunity", title: "AI Bubble or Boom? Analysts weigh in on NVIDIA", source: "Reuters", date: "1 day ago", img: "https://picsum.photos/seed/news3/300/160" }, | |
| { fund: "General", title: "RBI Monetary Policy Update: Impact on Mutual Funds", source: "Bloomberg", date: "1 day ago", img: "https://picsum.photos/seed/news4/300/160" }, | |
| { fund: "BlueChip Growth Fund", title: "Portfolio Rebalancing: BlueChip shifts towards Energy", source: "LiveMint", date: "2 days ago", img: "https://picsum.photos/seed/news5/300/160" }, | |
| { fund: "MidCap Alpha Fund", title: "Regulatory changes in Mid-cap classification", source: "Financial Express", date: "3 days ago", img: "https://picsum.photos/seed/news6/300/160" }, | |
| ]; | |
| /* --- APP LOGIC --- */ | |
| function init() { | |
| renderDashboardCharts(); | |
| renderFundTable(); | |
| renderAlerts(); | |
| renderNews(); | |
| updateNotificationBadge(); | |
| } | |
| function showSection(sectionId) { | |
| document.querySelectorAll('section').forEach(s => s.classList.add('hidden')); | |
| document.getElementById(sectionId).classList.remove('hidden'); | |
| document.querySelectorAll('.nav-item').forEach(item => item.classList.remove('active')); | |
| event.currentTarget.classList.add('active'); | |
| const titles = { | |
| 'dashboard': 'Portfolio Overview', | |
| 'portfolio': 'Detailed Portfolio Analysis', | |
| 'alerts': 'Intelligence Alerts', | |
| 'news': 'Market News Feed' | |
| }; | |
| document.getElementById('section-title').innerText = titles[sectionId]; | |
| } | |
| function updateNotificationBadge() { | |
| const alerts = FUNDS_DATA.filter(f => f.changes.managerChanged || f.changes.categoryChanged || f.changes.objectiveChanged).length; | |
| document.getElementById('alert-count').innerText = alerts; | |
| } | |
| function renderDashboardCharts() { | |
| const ctx = document.getElementById('performanceChart').getContext('2d'); | |
| new Chart(ctx, { | |
| type: 'line', | |
| data: { | |
| labels: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], | |
| datasets: [ | |
| { | |
| label: 'My Portfolio', | |
| data: [10, 12, 11, 14, 16, 15, 18, 20, 19, 22, 25, 28], | |
| borderColor: '#2563eb', | |
| backgroundColor: 'rgba(37, 99, 235, 0.1)', | |
| fill: true, | |
| tension: 0.4 | |
| }, | |
| { | |
| label: 'Category Average', | |
| data: [10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], | |
| borderColor: '#64748b', | |
| borderDash: [5, 5], | |
| fill: false, | |
| tension: 0.4 | |
| }, | |
| { | |
| label: 'Benchmark Index', | |
| data: [10, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20], | |
| borderColor: '#94a3b8', | |
| fill: false, | |
| tension: 0.4 | |
| } | |
| ] | |
| }, | |
| options: { | |
| responsive: true, | |
| maintainAspectRatio: false, | |
| plugins: { | |
| legend: { position: 'bottom' } | |
| }, | |
| scales: { | |
| y: { beginAtZero: false, grid: { display: false } }, | |
| x: { grid: { display: false } } | |
| } | |
| } | |
| }); | |
| } | |
| function renderFundTable() { | |
| const tbody = document.getElementById('fund-table-body'); | |
| tbody.innerHTML = FUNDS_DATA.map(fund => ` | |
| <tr> | |
| <td style="font-weight: 600;">${fund.name}</td> | |
| <td>${fund.category}</td> | |
| <td style="color: var(--success); font-weight: 600;">${fund.performance}%</td> | |
| <td>${fund.benchmark}%</td> | |
| <td> | |
| <span class="change-pill ${fund.performance > fund.benchmark ? 'pill-buy' : 'pill-sell'}"> | |
| ${fund.performance > fund.benchmark ? 'Outperforming' : 'Underperforming'} | |
| </span> | |
| </td> | |
| <td> | |
| <button onclick="openFundDetails(${fund.id})" style="padding: 6px 12px; border-radius: 6px; border: 1px solid var(--primary); background: transparent; color: var(--primary); cursor: pointer; font-weight: 500;"> | |
| Analyze | |
| </button> | |
| </td> | |
| </tr> | |
| `).join(''); | |
| } | |
| function renderAlerts() { | |
| const quickContainer = document.getElementById('quick-alerts'); | |
| const fullContainer = document.getElementById('full-alerts-list'); | |
| let alertsHtml = ''; | |
| FUNDS_DATA.forEach(fund => { | |
| if (fund.changes.managerChanged) { | |
| alertsHtml += ` | |
| <div class="alert-item critical"> | |
| <i class="fa-solid fa-circle-exclamation" style="color: var(--danger)"></i> | |
| <div class="alert-content"> | |
| <h4>Fund Manager Change</h4> | |
| <p><strong>${fund.name}</strong>: Manager changed from ${fund.changes.managerOld} to ${fund.manager}.</p> | |
| </div> | |
| </div>`; | |
| } | |
| if (fund.changes.categoryChanged) { | |
| alertsHtml += ` | |
| <div class="alert-item warning"> | |
| <i class="fa-solid fa-triangle-exclamation" style="color: var(--warning)"></i> | |
| <div class="alert-content"> | |
| <h4>Category Reclassification</h4> | |
| <p><strong>${fund.name}</strong>: Category changed from ${fund.changes.categoryOld} to ${fund.category}.</p> | |
| </div> | |
| </div>`; | |
| } | |
| if (fund.changes.objectiveChanged) { | |
| alertsHtml += ` | |
| <div class="alert-item"> | |
| <i class="fa-solid fa-circle-info" style="color: var(--primary)"></i> | |
| <div class="alert-content"> | |
| <h4>Investment Objective Update</h4> | |
| <p><strong>${fund.name}</strong> has updated its investment objective in the latest factsheet.</p> | |
| </div> | |
| </div>`; | |
| } | |
| }); | |
| quickContainer.innerHTML = alertsHtml.substring(0, 600) + (alertsHtml.length > 600 ? '...' : ''); | |
| fullContainer.innerHTML = alertsHtml || '<p style="text-align: center; color: var(--text-muted);">No critical alerts at this time.</p>'; | |
| } | |
| function renderNews() { | |
| const container = document.getElementById('news-container'); | |
| container.innerHTML = MOCK_NEWS.map(item => ` | |
| <div class="news-card"> | |
| <img src="${item.img}" class="news-img" alt="news"> | |
| <div class="news-body"> | |
| <span class="news-tag">${item.fund}</span> | |
| <div class="news-title">${item.title}</div> | |
| <div style="display: flex; justify-content: space-between; align-items: center; font-size: 0.75rem; color: var(--text-muted);"> | |
| <span><i class="fa-solid fa-building"></i> ${item.source}</span> | |
| <span>${item.date}</span> | |
| </div> | |
| </div> | |
| </div> | |
| `).join(''); | |
| } | |
| function openFundDetails(id) { | |
| const fund = FUNDS_DATA.find(f => f.id === id); | |
| const modal = document.getElementById('fund-modal'); | |
| const content = document.getElementById('modal-content'); | |
| content.innerHTML = ` | |
| <div style="display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: 2rem;"> | |
| <div> | |
| <h2 style="font-size: 1.8rem; margin-bottom: 0.5rem;">${fund.name}</h2> | |
| <p style="color: var(--text-muted)">${fund.category} | Manager: ${fund.manager}</p> | |
| </div> | |
| <div style="text-align: right"> | |
| <div style="font-size: 1.5rem; font-weight: 700; color: var(--success)">${fund.performance}%</div> | |
| <div style="font-size: 0.8rem; color: var(--text-muted)">1 Year Return</div> | |
| </div> | |
| </div> | |
| <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 2rem;"> | |
| <div> | |
| <h4 style="margin-bottom: 1rem; display: flex; align-items: center; gap: 10px;"> | |
| <i class="fa-solid fa-list-check" style="color: var(--primary)"></i> | |
| Monthly Stock Changes | |
| </h4> | |
| <div class="data-table-container"> | |
| <table> | |
| <thead> | |
| <tr> | |
| <th>Stock</th> | |
| <th>Prev %</th> | |
| <th>Curr %</th> | |
| <th>Action</th> | |
| </tr> | |
| </thead> | |
| <tbody> | |
| ${fund.stocks.map(s => ` | |
| <tr> | |
| <td>${s.name}</td> | |
| <td>${s.prev}%</td> | |
| <td>${s.curr}%</td> | |
| <td><span class="change-pill ${s.action === 'Buy' ? 'pill-buy' : 'pill-sell'}">${s.action}</span></td> | |
| </tr> | |
| `).join('')} | |
| </tbody> | |
| </table> | |
| </div> | |
| </div> | |
| <div> | |
| <h4 style="margin-bottom: 1rem; display: flex; align-items: center; gap: 10px;"> | |
| <i class="fa-solid fa-chart-pie" style="color: var(--primary)"></i> | |
| Sector Weight Change | |
| </h4> | |
| <div class="data-table-container"> | |
| <table> | |
| <thead> | |
| <tr> | |
| <th>Sector</th> | |
| <th>Prev %</th> | |
| <th>Curr %</th> | |
| <th>Change</th> | |
| </tr> | |
| </thead> | |
| <tbody> | |
| ${fund.sectors.map(s => { | |
| const diff = s.curr - s.prev; | |
| return ` | |
| <tr> | |
| <td>${s.name}</td> | |
| <td>${s.prev}%</td> | |
| <td>${s.curr}%</td> | |
| <td style="color: ${diff >= 0 ? 'var(--success)' : 'var(--danger)'}; font-weight: 600;"> | |
| ${diff >= 0 ? '+' : ''}${diff}% | |
| </td> | |
| </tr>`; | |
| }).join('')} | |
| </tbody> | |
| </table> | |
| </div> | |
| </div> | |
| </div> | |
| <div style="margin-top: 2rem; padding: 1.5rem; background: #f8fafc; border-radius: 12px; border: 1px solid var(--border);"> | |
| <h4 style="margin-bottom: 0.5rem;">Investment Objective</h4> | |
| <p style="font-size: 0.9rem; color: var(--text-muted); line-height: 1.6;">${fund.objective}</p> | |
| </div> | |
| `; | |
| modal.style.display = 'flex'; | |
| } | |
| function closeModal() { | |
| document.getElementById('fund-modal').style.display = 'none'; | |
| } | |
| // Close modal when clicking outside | |
| window.onclick = function(event) { | |
| const modal = document.getElementById('fund-modal'); | |
| if (event.target == modal) { | |
| closeModal(); | |
| } | |
| } | |
| // Start the app | |
| window.onload = init; | |
| </script> | |
| </body> | |
| </html> |