Really-amin's picture
Upload 577 files
b190b45 verified
<!DOCTYPE html>
<html lang="en" dir="ltr" data-theme="dark">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="Crypto Monitor - Premium Dashboard with Real-time Market Data, AI Analysis & Sentiment">
<meta name="theme-color" content="#8B5CF6">
<title>Dashboard | Crypto Monitor</title>
<!-- Favicon -->
<link rel="icon" type="image/svg+xml" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Cdefs%3E%3ClinearGradient id='g' x1='0%25' y1='0%25' x2='100%25' y2='100%25'%3E%3Cstop offset='0%25' stop-color='%238B5CF6'/%3E%3Cstop offset='100%25' stop-color='%236D28D9'/%3E%3C/linearGradient%3E%3C/defs%3E%3Ccircle cx='50' cy='50' r='45' fill='url(%23g)'/%3E%3Ctext x='50' y='65' font-size='50' text-anchor='middle' fill='white' font-weight='bold'%3EC%3C/text%3E%3C/svg%3E">
<!-- Preconnect to external domains -->
<link rel="preconnect" href="https://fonts.googleapis.com" crossorigin>
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="dns-prefetch" href="https://fonts.googleapis.com">
<!-- Critical CSS - Inline for faster first paint -->
<style>
/* Critical above-the-fold styles - Cursor-inspired */
:root{
--bg-primary:#0A0A0A;
--surface-primary:#1E1E1E;
--text-primary:#EFEFEF;
--accent-purple:#8B5CF6;
--sidebar-width:240px;
}
*,*::before,*::after{margin:0;padding:0;box-sizing:border-box}
html{font-size:15px;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}
body{font-family:'Inter',-apple-system,BlinkMacSystemFont,system-ui,sans-serif;font-size:15px;line-height:1.5;color:var(--text-primary);background:var(--bg-primary);min-height:100vh}
.app-container{display:flex;min-height:100vh}
.sidebar{position:fixed;left:0;top:0;bottom:0;width:var(--sidebar-width);background:#0F0F0F;border-right:1px solid #2A2A2A;z-index:1200;transition:width 300ms cubic-bezier(0.4,0,0.2,1)}
.main-content{flex:1;margin-left:var(--sidebar-width);min-height:100vh;display:flex;flex-direction:column;transition:margin-left 300ms cubic-bezier(0.4,0,0.2,1)}
.page-content{padding:24px;max-width:1400px;margin:0 auto;width:100%}
@media(max-width:1024px){.sidebar{transform:translateX(-100%)}.main-content{margin-left:0}}
</style>
<!-- Cursor-Inspired Design System -->
<link rel="stylesheet" href="/static/shared/css/design-system-cursor.css">
<link rel="stylesheet" href="/static/shared/css/layout-cursor.css">
<link rel="stylesheet" href="/static/shared/css/components-cursor.css">
<link rel="stylesheet" href="/static/shared/css/animations-cursor.css">
<!-- Page-specific CSS -->
<link rel="stylesheet" href="/static/pages/dashboard/dashboard.css?v=4.0">
<!-- Error Suppressor -->
<script src="/static/shared/js/utils/error-suppressor.js"></script>
<!-- Crypto Icons Library -->
<script src="/static/assets/icons/crypto-icons.js"></script>
<!-- API Configuration -->
<script src="/static/js/api-config.js"></script>
<script>
// Initialize API client
window.apiReady = new Promise((resolve) => {
if (window.apiClient) {
console.log('✅ API Client ready');
resolve(window.apiClient);
} else {
console.error('❌ API Client not loaded');
}
});
</script>
</head>
<body>
<div class="app-container">
<!-- Sidebar -->
<aside id="sidebar-container"></aside>
<!-- Main Content -->
<main class="main-content">
<!-- Header -->
<header id="header-container"></header>
<!-- Dashboard Content -->
<div class="page-content stagger-fade-in">
<!-- Page Header -->
<div class="page-header">
<h1 class="page-title">Dashboard</h1>
<p class="page-description">Real-time Market Data & AI Analysis</p>
</div>
<!-- Stats Grid -->
<div id="stats-grid" style="display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: var(--space-4); margin-bottom: var(--space-8);">
<!-- Stats cards will be injected here -->
<div class="stat-card skeleton-wave" style="min-height: 140px;"></div>
<div class="stat-card skeleton-wave" style="min-height: 140px;"></div>
<div class="stat-card skeleton-wave" style="min-height: 140px;"></div>
<div class="stat-card skeleton-wave" style="min-height: 140px;"></div>
</div>
<!-- Charts & Analysis -->
<div style="display: grid; grid-template-columns: 1fr; gap: var(--space-6); margin-bottom: var(--space-8);">
<!-- Market Overview Chart -->
<div class="card" id="market-chart-container">
<div class="card-header">
<div>
<h3 class="card-title">Market Overview</h3>
<p class="card-subtitle">Real-time price movements</p>
</div>
<div style="display: flex; gap: var(--space-2);">
<button class="btn btn-ghost btn-sm" data-timeframe="1h">1H</button>
<button class="btn btn-ghost btn-sm" data-timeframe="4h">4H</button>
<button class="btn btn-secondary btn-sm" data-timeframe="1d">1D</button>
<button class="btn btn-ghost btn-sm" data-timeframe="1w">1W</button>
</div>
</div>
<div class="card-body">
<div id="market-chart" style="min-height: 400px; display: flex; align-items: center; justify-content: center;">
<div class="spinner spinner-lg"></div>
</div>
</div>
</div>
</div>
<!-- Two Column Layout -->
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(450px, 1fr)); gap: var(--space-6); margin-bottom: var(--space-8);">
<!-- Top Gainers -->
<div class="card">
<div class="card-header">
<h3 class="card-title">Top Gainers</h3>
<span class="badge badge-success pill">24h</span>
</div>
<div class="card-body">
<div id="top-gainers-list">
<!-- Skeleton loaders -->
<div style="display: flex; flex-direction: column; gap: var(--space-3);">
<div class="skeleton skeleton-text"></div>
<div class="skeleton skeleton-text"></div>
<div class="skeleton skeleton-text"></div>
</div>
</div>
</div>
</div>
<!-- Top Losers -->
<div class="card">
<div class="card-header">
<h3 class="card-title">Top Losers</h3>
<span class="badge badge-danger pill">24h</span>
</div>
<div class="card-body">
<div id="top-losers-list">
<!-- Skeleton loaders -->
<div style="display: flex; flex-direction: column; gap: var(--space-3);">
<div class="skeleton skeleton-text"></div>
<div class="skeleton skeleton-text"></div>
<div class="skeleton skeleton-text"></div>
</div>
</div>
</div>
</div>
</div>
<!-- AI Sentiment Analysis -->
<div class="card" id="sentiment-container">
<div class="card-header">
<div>
<h3 class="card-title">AI Sentiment Analysis</h3>
<p class="card-subtitle">Market sentiment powered by AI models</p>
</div>
<span class="badge badge-primary">AI</span>
</div>
<div class="card-body">
<div id="sentiment-content" style="min-height: 200px; display: flex; align-items: center; justify-content: center;">
<div class="dots-loader">
<span></span>
<span></span>
<span></span>
</div>
</div>
</div>
</div>
<!-- Recent Activity / News -->
<div class="card" style="margin-top: var(--space-6);" id="recent-activity">
<div class="card-header">
<h3 class="card-title">Recent Activity</h3>
<button class="btn btn-ghost btn-sm">View All</button>
</div>
<div class="card-body">
<div id="activity-list">
<!-- Activity items will be injected here -->
<div style="display: flex; flex-direction: column; gap: var(--space-3);">
<div class="skeleton skeleton-text"></div>
<div class="skeleton skeleton-text"></div>
<div class="skeleton skeleton-text"></div>
</div>
</div>
</div>
</div>
<!-- Footer Info -->
<div style="margin-top: var(--space-16); padding-top: var(--space-6); border-top: 1px solid var(--border-default); text-align: center; color: var(--text-tertiary); font-size: var(--text-sm);">
<p>Last updated: <span id="footer-last-update">Just now</span></p>
</div>
</div>
</main>
</div>
<!-- Toast Container -->
<div id="toast-container" aria-live="polite"></div>
<script type="module">
// Defer non-critical initialization
(async function() {
const initApp = async () => {
try {
// Load layout (header + sidebar)
const { LayoutManager } = await import('/static/shared/js/core/layout-manager.js?v=4.0');
await LayoutManager.init('dashboard');
// Load dashboard module after layout is ready
const { default: dashboardPage } = await import('/static/pages/dashboard/dashboard.js?v=4.0');
window.dashboardPage = dashboardPage;
window.addEventListener('beforeunload', () => {
if (window.dashboardPage) window.dashboardPage.destroy();
});
console.log('✅ Dashboard initialized with Cursor UI');
} catch (error) {
console.error('❌ Failed to initialize dashboard:', error);
// Show error alert
const pageContent = document.querySelector('.page-content');
if (pageContent) {
pageContent.insertAdjacentHTML('afterbegin', `
<div class="alert alert-danger" style="margin-bottom: var(--space-6);">
<svg class="alert-icon" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<circle cx="12" cy="12" r="10"/>
<line x1="12" y1="8" x2="12" y2="12"/>
<line x1="12" y1="16" x2="12.01" y2="16"/>
</svg>
<div class="alert-content">
<div class="alert-title">Initialization Error</div>
<div class="alert-message">Failed to load dashboard. Please refresh the page.</div>
</div>
</div>
`);
}
}
};
// Use requestIdleCallback if available, otherwise setTimeout
if (window.requestIdleCallback) {
window.requestIdleCallback(initApp, { timeout: 2000 });
} else {
setTimeout(initApp, 100);
}
})();
</script>
</body>
</html>