mirror of
https://github.com/chrisnov-it/quantumbotx.git
synced 2026-07-28 03:07:53 +00:00
8923c99f7a
- Tailwind CDN configured with darkMode: 'class' - Dark mode toggle in header (sun/moon icon), persisted via localStorage - base.html: sidebar, header, search, nav, profile — all dark: variants - index.html: stat cards, chart containers, activities, bot list — all dark: variants - style.css: dark scrollbar styling - Prevents flash by checking localStorage before page render Co-Authored-By: Claude <noreply@anthropic.com>
205 lines
15 KiB
HTML
205 lines
15 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title data-i18n-key="{% block title_key %}dashboard.title{% endblock %}">{% block title %}Dashboard{% endblock %} - QuantumBotX</title>
|
|
<script src="https://cdn.tailwindcss.com"></script>
|
|
<script>
|
|
tailwind.config = {
|
|
darkMode: 'class',
|
|
}
|
|
</script>
|
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
|
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
|
<link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
|
|
<!-- Toastify CSS -->
|
|
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/toastify-js/src/toastify.min.css">
|
|
{% block head_extra %}{% endblock %}
|
|
<style id="holiday-styles"></style>
|
|
</head>
|
|
<body class="bg-gray-100 dark:bg-slate-900 font-sans">
|
|
<!-- Theme Toggle Script (must run before page render) -->
|
|
<script>
|
|
if (localStorage.getItem('dark-mode') === 'true') {
|
|
document.documentElement.classList.add('dark');
|
|
}
|
|
</script>
|
|
<!-- Holiday Banner -->
|
|
<div id="holiday-banner" class="hidden bg-gradient-to-r from-blue-500 to-purple-600 text-white py-2 px-4 text-center relative">
|
|
<div class="container mx-auto flex justify-between items-center">
|
|
<div id="holiday-greeting" class="font-medium"></div>
|
|
<div id="holiday-countdown" class="text-sm opacity-90"></div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="flex h-screen overflow-hidden">
|
|
<!-- SIDEBAR -->
|
|
<div id="sidebar" class="sidebar bg-white dark:bg-slate-800 w-64 shadow-lg dark:shadow-slate-900/50 flex flex-col">
|
|
<div class="p-4 flex items-center border-b dark:border-slate-700">
|
|
<div class="w-10 h-10 rounded-full bg-gradient-to-r from-indigo-600 to-violet-600 flex items-center justify-center text-white font-bold">QT</div>
|
|
<div class="ml-3 logo-text">
|
|
<h1 class="text-xl font-bold text-gray-800 dark:text-white">QuantumBotX</h1>
|
|
<p class="text-xs text-gray-500 dark:text-gray-400">The AI-Powered Strategy Platform</p>
|
|
</div>
|
|
</div>
|
|
<div class="flex-1 overflow-y-auto">
|
|
<nav class="mt-6">
|
|
<div class="px-4 mb-4"><p class="text-xs font-semibold text-gray-500 dark:text-gray-400 uppercase tracking-wider sidebar-text" data-i18n="nav.section.navigation">Navigation</p></div>
|
|
<a href="/" class="nav-item flex items-center px-4 py-3 text-gray-600 dark:text-gray-300 hover:text-indigo-600 dark:hover:text-indigo-400 hover:bg-indigo-50 dark:hover:bg-slate-700/50 {% if active_page == 'dashboard' %}active{% endif %}"><i class="fas fa-chart-line w-5"></i><span class="ml-3 sidebar-text" data-i18n="nav.dashboard">Dashboard</span></a>
|
|
<a href="/trading_bots" class="nav-item flex items-center px-4 py-3 text-gray-600 dark:text-gray-300 hover:text-indigo-600 dark:hover:text-indigo-400 hover:bg-indigo-50 dark:hover:bg-slate-700/50 {% if active_page == 'trading_bots' %}active{% endif %}"><i class="fas fa-robot w-5"></i><span class="ml-3 sidebar-text" data-i18n="nav.bots">Trading Bots</span></a>
|
|
<a href="/portfolio" class="nav-item flex items-center px-4 py-3 text-gray-600 dark:text-gray-300 hover:text-indigo-600 dark:hover:text-indigo-400 hover:bg-indigo-50 dark:hover:bg-slate-700/50 {% if active_page == 'portfolio' %}active{% endif %}"><i class="fas fa-wallet w-5"></i><span class="ml-3 sidebar-text" data-i18n="nav.portfolio">Portfolio</span></a>
|
|
<a href="/backtesting" class="nav-item flex items-center px-4 py-3 text-gray-600 dark:text-gray-300 hover:text-indigo-600 dark:hover:text-indigo-400 hover:bg-indigo-50 dark:hover:bg-slate-700/50 {% if active_page == 'backtesting' %}active{% endif %}"><i class="fas fa-vial w-5"></i><span class="ml-3 sidebar-text" data-i18n="nav.backtest">Backtester</span></a>
|
|
<a href="/ai-mentor" class="nav-item flex items-center px-4 py-3 text-gray-600 dark:text-gray-300 hover:text-indigo-600 dark:hover:text-indigo-400 hover:bg-indigo-50 dark:hover:bg-slate-700/50 {% if active_page == 'ai_mentor' %}active{% endif %}"><i class="fas fa-brain w-5"></i><span class="ml-3 sidebar-text" data-i18n="nav.ai_mentor">AI Mentor</span></a>
|
|
<a href="/strategy-switcher" class="nav-item flex items-center px-4 py-3 text-gray-600 dark:text-gray-300 hover:text-indigo-600 dark:hover:text-indigo-400 hover:bg-indigo-50 dark:hover:bg-slate-700/50 {% if active_page == 'strategy_switcher' %}active{% endif %}"><i class="fas fa-sync-alt w-5"></i><span class="ml-3 sidebar-text" data-i18n="nav.strategy_switcher">Strategy Switcher</span></a>
|
|
<a href="/ramadan" id="ramadan-nav-link" class="nav-item flex items-center px-4 py-3 text-gray-600 dark:text-gray-300 hover:text-indigo-600 dark:hover:text-indigo-400 hover:bg-indigo-50 dark:hover:bg-slate-700/50 {% if active_page == 'ramadan' %}active{% endif %} hidden"><i class="fas fa-moon w-5"></i><span class="ml-3 sidebar-text" data-i18n="nav.ramadan">Ramadan Mode</span></a>
|
|
<a href="/history" class="nav-item flex items-center px-4 py-3 text-gray-600 dark:text-gray-300 hover:text-indigo-600 dark:hover:text-indigo-400 hover:bg-indigo-50 dark:hover:bg-slate-700/50 {% if active_page == 'history' %}active{% endif %}"><i class="fas fa-history w-5"></i><span class="ml-3 sidebar-text" data-i18n="nav.history">History</span></a>
|
|
<a href="/settings" class="nav-item flex items-center px-4 py-3 text-gray-600 dark:text-gray-300 hover:text-indigo-600 dark:hover:text-indigo-400 hover:bg-indigo-50 dark:hover:bg-slate-700/50 {% if active_page == 'settings' %}active{% endif %}"><i class="fas fa-cog w-5"></i><span class="ml-3 sidebar-text" data-i18n="nav.settings">Settings</span></a>
|
|
<div class="px-4 mt-8 mb-4"><p class="text-xs font-semibold text-gray-500 dark:text-gray-400 uppercase tracking-wider sidebar-text" data-i18n="nav.section.market_data">Market Data</p></div>
|
|
<a href="/stocks" class="nav-item flex items-center px-4 py-3 text-gray-600 dark:text-gray-300 hover:text-indigo-600 dark:hover:text-indigo-400 hover:bg-indigo-50 dark:hover:bg-slate-700/50 {% if active_page == 'stocks' %}active{% endif %}"><i class="fas fa-chart-bar w-5"></i><span class="ml-3 sidebar-text" data-i18n="nav.stocks">Stocks</span></a>
|
|
<a href="/forex" class="nav-item flex items-center px-4 py-3 text-gray-600 dark:text-gray-300 hover:text-indigo-600 dark:hover:text-indigo-400 hover:bg-indigo-50 dark:hover:bg-slate-700/50 {% if active_page == 'forex' %}active{% endif %}"><i class="fas fa-exchange-alt w-5"></i><span class="ml-3 sidebar-text" data-i18n="nav.forex">Forex</span></a>
|
|
</nav>
|
|
</div>
|
|
<div class="p-4 border-t dark:border-slate-700">
|
|
<a href="/profile" class="flex items-center group">
|
|
<div class="w-10 h-10 rounded-full bg-gray-200 dark:bg-slate-600 flex items-center justify-center"><i class="fas fa-user text-gray-600 dark:text-gray-300"></i></div>
|
|
<div class="ml-3 sidebar-text"><p class="text-sm font-medium text-gray-800 dark:text-white group-hover:text-indigo-600">Reynov Christian</p><p class="text-xs text-gray-500 dark:text-gray-400 group-hover:text-indigo-600">Developer</p></div>
|
|
</a>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- MAIN CONTENT -->
|
|
<div class="flex-1 overflow-auto">
|
|
<header class="bg-white dark:bg-slate-800 shadow-sm dark:shadow-slate-900/50">
|
|
<div class="flex items-center justify-between px-6 py-4">
|
|
<div class="flex items-center">
|
|
<button id="sidebar-toggle" class="text-gray-500 dark:text-gray-400 focus:outline-none"><i class="fas fa-bars"></i></button>
|
|
<div class="ml-4 relative">
|
|
<input type="text" class="w-64 px-4 py-2 rounded-lg border border-gray-300 dark:border-slate-600 bg-white dark:bg-slate-700 text-gray-900 dark:text-white placeholder-gray-400 dark:placeholder-gray-500 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:border-transparent" placeholder="Search markets, bots..." />
|
|
<i class="fas fa-search absolute right-3 top-3 text-gray-400 dark:text-gray-500"></i>
|
|
</div>
|
|
</div>
|
|
<div class="flex items-center space-x-4">
|
|
<!-- Dark Mode Toggle -->
|
|
<button id="dark-mode-toggle" class="p-2 rounded-lg hover:bg-gray-100 dark:hover:bg-slate-700 text-gray-500 dark:text-gray-400 transition-colors" title="Toggle Dark Mode">
|
|
<i id="dark-mode-icon" class="fas fa-moon"></i>
|
|
</button>
|
|
<!-- Global Language Switcher -->
|
|
<div class="flex items-center space-x-1 bg-white dark:bg-slate-800 rounded-lg shadow-sm border dark:border-slate-700 px-2 py-1">
|
|
<button class="lang-btn px-2 py-1 text-xs rounded font-medium hover:bg-gray-100 transition-colors" data-lang="id">ID</button>
|
|
<button class="lang-btn px-2 py-1 text-xs rounded font-medium hover:bg-gray-100 transition-colors" data-lang="en">EN</button>
|
|
</div>
|
|
<a href="/notifications" class="relative text-gray-500 dark:text-gray-400 hover:text-indigo-600 dark:hover:text-indigo-400"><i class="fas fa-bell"></i><span id="notification-dot" class="absolute top-0 right-0 w-2 h-2 rounded-full bg-red-500 hidden"></span></a>
|
|
<a href="/profile" class="w-8 h-8 rounded-full bg-gray-200 dark:bg-slate-600 flex items-center justify-center hover:bg-gray-300 dark:hover:bg-slate-500"><i class="fas fa-user text-gray-600 dark:text-gray-300"></i></a>
|
|
</div>
|
|
</div>
|
|
</header>
|
|
|
|
<!-- Ini adalah area di mana konten unik setiap halaman akan disuntikkan -->
|
|
<main class="p-6">
|
|
{% block content %}{% endblock %}
|
|
</main>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Skrip yang dibutuhkan oleh semua halaman -->
|
|
<!-- Toastify JS -->
|
|
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/toastify-js"></script>
|
|
<!-- Internationalization (i18n) System -->
|
|
<script src="{{ url_for('static', filename='js/i18n.js') }}"></script>
|
|
<script src="{{ url_for('static', filename='js/main.js') }}"></script>
|
|
<!-- Holiday Detection Script -->
|
|
<script>
|
|
// Function to apply holiday theme
|
|
function applyHolidayTheme(theme) {
|
|
const styleElement = document.getElementById('holiday-styles');
|
|
if (!styleElement) return;
|
|
|
|
let css = '';
|
|
if (theme.background_gradient) {
|
|
css += `body { background: ${theme.background_gradient}; }`;
|
|
}
|
|
if (theme.primary_color) {
|
|
css += `:root { --holiday-primary: ${theme.primary_color}; }`;
|
|
}
|
|
if (theme.secondary_color) {
|
|
css += `:root { --holiday-secondary: ${theme.secondary_color}; }`;
|
|
}
|
|
if (theme.accent_color) {
|
|
css += `:root { --holiday-accent: ${theme.accent_color}; }`;
|
|
}
|
|
|
|
styleElement.textContent = css;
|
|
}
|
|
|
|
// Function to check for active holidays
|
|
async function checkHolidayStatus() {
|
|
try {
|
|
const response = await fetch('/api/holiday/status');
|
|
const data = await response.json();
|
|
|
|
if (data.success && data.is_holiday) {
|
|
// Show holiday banner
|
|
const banner = document.getElementById('holiday-banner');
|
|
const greeting = document.getElementById('holiday-greeting');
|
|
const countdown = document.getElementById('holiday-countdown');
|
|
|
|
if (banner && greeting) {
|
|
greeting.textContent = data.greeting;
|
|
banner.classList.remove('hidden');
|
|
|
|
// Apply holiday theme
|
|
if (data.ui_theme) {
|
|
applyHolidayTheme(data.ui_theme);
|
|
}
|
|
|
|
// Special handling for Ramadan features
|
|
if (data.holiday_name === "Ramadan Trading Mode" && data.ramadan_features) {
|
|
// Show the Ramadan navigation link since mode is active
|
|
const ramadanLink = document.getElementById('ramadan-nav-link');
|
|
if (ramadanLink) {
|
|
ramadanLink.classList.remove('hidden');
|
|
}
|
|
|
|
// Show Iftar countdown if available
|
|
if (data.ramadan_features.iftar_countdown) {
|
|
const countdownData = data.ramadan_features.iftar_countdown;
|
|
countdown.textContent = `${countdownData.hours}h ${countdownData.minutes}m until ${countdownData.next_prayer}`;
|
|
}
|
|
}
|
|
|
|
// Special handling for Christmas features
|
|
if (data.holiday_name === "Christmas Trading Mode") {
|
|
// Show countdown if it's close to Christmas
|
|
const today = new Date();
|
|
const christmasDate = new Date(today.getFullYear(), 11, 25); // December 25
|
|
const timeDiff = christmasDate - today;
|
|
const daysDiff = Math.ceil(timeDiff / (1000 * 60 * 60 * 24));
|
|
|
|
if (daysDiff >= 0 && daysDiff <= 10) {
|
|
countdown.textContent = `${daysDiff} days until Christmas`;
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
// Hide Ramadan navigation link when no holiday is active
|
|
const ramadanLink = document.getElementById('ramadan-nav-link');
|
|
if (ramadanLink) {
|
|
ramadanLink.classList.add('hidden');
|
|
}
|
|
}
|
|
} catch (error) {
|
|
console.error('Error checking holiday status:', error);
|
|
}
|
|
}
|
|
|
|
// Check for holidays on page load
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
checkHolidayStatus();
|
|
});
|
|
</script>
|
|
<!-- Blok untuk skrip spesifik halaman -->
|
|
{% block scripts %}{% endblock %}
|
|
</body>
|
|
</html>
|