File size: 11,317 Bytes
b190b45
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
<!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>