Spaces:
Sleeping
Sleeping
| <html lang="ar" dir="rtl"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>لوحة إشارات التداول</title> | |
| <!-- Bootstrap RTL CSS --> | |
| <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.rtl.min.css"> | |
| <!-- Font Awesome --> | |
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> | |
| <!-- Google Font - Cairo --> | |
| <link href="https://fonts.googleapis.com/css2?family=Cairo:wght@400;500;600;700&display=swap" rel="stylesheet"> | |
| <!-- Custom CSS --> | |
| <style> | |
| :root { | |
| --primary-color: #3498db; | |
| --secondary-color: #2c3e50; | |
| --success-color: #2ecc71; | |
| --danger-color: #e74c3c; | |
| --warning-color: #f39c12; | |
| --info-color: #1abc9c; | |
| --light-color: #f8f9fa; | |
| --dark-color: #343a40; | |
| } | |
| body { | |
| font-family: 'Cairo', sans-serif; | |
| background-color: #f5f7fa; | |
| color: #333; | |
| padding-bottom: 60px; | |
| } | |
| .navbar { | |
| background-color: var(--secondary-color); | |
| box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); | |
| } | |
| .navbar-brand { | |
| font-weight: 700; | |
| color: white ; | |
| } | |
| .dashboard-header { | |
| background-color: white; | |
| border-radius: 15px; | |
| box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08); | |
| padding: 25px; | |
| margin-bottom: 25px; | |
| } | |
| .status-card { | |
| border-radius: 15px; | |
| box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08); | |
| transition: all 0.3s ease; | |
| border: none; | |
| overflow: hidden; | |
| } | |
| .status-card:hover { | |
| transform: translateY(-5px); | |
| box-shadow: 0 8px 25px rgba(0, 0, 0, 0.12); | |
| } | |
| .status-card .card-body { | |
| padding: 25px; | |
| } | |
| .signal-card { | |
| border-radius: 15px; | |
| box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08); | |
| margin-bottom: 25px; | |
| transition: all 0.3s ease; | |
| overflow: hidden; | |
| border: none; | |
| } | |
| .signal-card:hover { | |
| transform: translateY(-5px); | |
| box-shadow: 0 8px 30px rgba(0, 0, 0, 0.12); | |
| } | |
| .signal-card .card-header { | |
| display: flex; | |
| justify-content: space-between; | |
| align-items: center; | |
| background-color: var(--secondary-color); | |
| color: white; | |
| font-weight: 600; | |
| padding: 18px 25px; | |
| } | |
| .signal-card .card-body { | |
| padding: 25px; | |
| } | |
| .signal-info { | |
| display: flex; | |
| flex-wrap: wrap; | |
| gap: 15px; | |
| } | |
| .signal-detail { | |
| flex: 1; | |
| min-width: 150px; | |
| background-color: #f8f9fa; | |
| padding: 15px 20px; | |
| border-radius: 12px; | |
| box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.05); | |
| } | |
| .signal-detail h6 { | |
| margin-bottom: 8px; | |
| color: var(--secondary-color); | |
| font-size: 15px; | |
| font-weight: 600; | |
| } | |
| .signal-detail p { | |
| margin-bottom: 0; | |
| font-weight: 500; | |
| font-size: 16px; | |
| } | |
| .reason-section { | |
| margin-top: 20px; | |
| background-color: #f8f9fa; | |
| padding: 20px; | |
| border-radius: 12px; | |
| box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.05); | |
| } | |
| .reason-section h6 { | |
| color: var(--secondary-color); | |
| font-weight: 600; | |
| margin-bottom: 12px; | |
| } | |
| .signal-actions { | |
| display: flex; | |
| justify-content: flex-end; | |
| gap: 15px; | |
| margin-top: 20px; | |
| } | |
| .btn-action { | |
| border-radius: 10px; | |
| padding: 10px 20px; | |
| font-weight: 500; | |
| display: flex; | |
| align-items: center; | |
| gap: 8px; | |
| transition: all 0.3s ease; | |
| } | |
| .btn-action:hover { | |
| transform: translateY(-3px); | |
| box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1); | |
| } | |
| .badge-buy { | |
| background-color: var(--success-color); | |
| color: white; | |
| padding: 6px 12px; | |
| border-radius: 8px; | |
| font-weight: 600; | |
| } | |
| .badge-sell { | |
| background-color: var(--danger-color); | |
| color: white; | |
| padding: 6px 12px; | |
| border-radius: 8px; | |
| font-weight: 600; | |
| } | |
| .badge-starting { | |
| background-color: var(--warning-color); | |
| color: white; | |
| padding: 6px 12px; | |
| border-radius: 8px; | |
| } | |
| .badge-active { | |
| background-color: var(--primary-color); | |
| color: white; | |
| padding: 6px 12px; | |
| border-radius: 8px; | |
| } | |
| .badge-completed { | |
| background-color: var(--success-color); | |
| color: white; | |
| padding: 6px 12px; | |
| border-radius: 8px; | |
| } | |
| .badge-failed { | |
| background-color: var(--danger-color); | |
| color: white; | |
| padding: 6px 12px; | |
| border-radius: 8px; | |
| } | |
| .add-signal-btn { | |
| position: fixed; | |
| bottom: 30px; | |
| right: 30px; | |
| width: 65px; | |
| height: 65px; | |
| border-radius: 50%; | |
| background-color: var(--primary-color); | |
| color: white; | |
| display: flex; | |
| justify-content: center; | |
| align-items: center; | |
| font-size: 24px; | |
| box-shadow: 0 5px 20px rgba(0, 0, 0, 0.2); | |
| transition: all 0.3s ease; | |
| z-index: 1000; | |
| border: none; | |
| } | |
| .add-signal-btn:hover { | |
| transform: scale(1.1); | |
| background-color: #2980b9; | |
| color: white; | |
| } | |
| .delete-all-btn { | |
| background-color: var(--danger-color); | |
| color: white; | |
| border: none; | |
| border-radius: 10px; | |
| padding: 12px 20px; | |
| font-weight: 500; | |
| transition: all 0.3s ease; | |
| display: flex; | |
| align-items: center; | |
| gap: 8px; | |
| } | |
| .delete-all-btn:hover { | |
| background-color: #c0392b; | |
| transform: translateY(-3px); | |
| box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1); | |
| } | |
| /* Custom Switch */ | |
| .switch { | |
| position: relative; | |
| display: inline-block; | |
| width: 80px; | |
| height: 80px; | |
| border: 2px solid #dcdcdc; | |
| background: #e0e0e0; | |
| box-shadow: 7px 7px 23px #bebebe, -7px -7px 23px #ffffff; | |
| overflow: hidden; | |
| border-radius: 60px; | |
| } | |
| .switch input { | |
| opacity: 0; | |
| width: 0; | |
| height: 0; | |
| } | |
| .slider { | |
| position: absolute; | |
| cursor: pointer; | |
| top: 0; | |
| left: 0; | |
| right: 0; | |
| bottom: 0; | |
| -webkit-transition: 0.5s; | |
| transition: 0.5s; | |
| } | |
| .chbox:checked + .slider:before { | |
| background: white; | |
| box-shadow: none; | |
| } | |
| .chbox:focus + .slider { | |
| box-shadow: 0 0 1px #2196f3; | |
| } | |
| .slider { | |
| color: #9a9a9a; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| font-size: 11px; | |
| font-family: 'Cairo', sans-serif; | |
| } | |
| .slider--0 { | |
| color: white; | |
| font-weight: 600; | |
| background-color: var(--success-color); | |
| } | |
| .slider--1 div { | |
| transition: 0.5s; | |
| } | |
| .slider--1 div { | |
| position: absolute; | |
| width: 100%; | |
| height: 50%; | |
| left: 0; | |
| } | |
| .chbox:checked ~ .slider--1 div:first-child { | |
| transform: translateY(-100%); | |
| transition-delay: 1s; | |
| } | |
| .chbox:checked ~ .slider--1 div:last-child { | |
| transform: translateY(100%); | |
| transition-delay: 1s; | |
| } | |
| .chbox:checked ~ .slider--2 { | |
| transform: translateX(100%); | |
| transition-delay: 0.5s; | |
| } | |
| .chbox:checked ~ .slider--3 { | |
| transform: translateX(-100%); | |
| transition-delay: 0s; | |
| } | |
| .slider--1 div:first-child { | |
| transform: translateY(0); | |
| top: 0; | |
| background-color: #f3f3f3; | |
| transition-delay: 0s; | |
| } | |
| .slider--1 div:last-child { | |
| transform: translateY(0); | |
| bottom: 0; | |
| background-color: #f3f3f3; | |
| border-top: 1px solid #e0e0e0; | |
| transition-delay: 0s; | |
| } | |
| .slider--2 { | |
| background-color: #e6e6e6; | |
| transition-delay: 0.5s; | |
| transform: translateX(0); | |
| border-left: 1px solid #d2d2d2; | |
| } | |
| .slider--3 { | |
| background-color: #d2d2d2; | |
| transition-delay: 1s; | |
| transform: translatex(0); | |
| border-right: 1px solid #d2d2d2; | |
| font-weight: 600; | |
| } | |
| /* Responsive adjustments */ | |
| @media (max-width: 768px) { | |
| .signal-info { | |
| flex-direction: column; | |
| gap: 10px; | |
| } | |
| .signal-detail { | |
| min-width: 100%; | |
| } | |
| .signal-actions { | |
| flex-wrap: wrap; | |
| } | |
| .dashboard-header h2 { | |
| font-size: 1.5rem; | |
| } | |
| .add-signal-btn { | |
| width: 55px; | |
| height: 55px; | |
| font-size: 20px; | |
| bottom: 20px; | |
| right: 20px; | |
| } | |
| .switch { | |
| width: 60px; | |
| height: 60px; | |
| } | |
| } | |
| /* Loading spinner */ | |
| .loading-overlay { | |
| position: fixed; | |
| top: 0; | |
| left: 0; | |
| width: 100%; | |
| height: 100%; | |
| background-color: rgba(255, 255, 255, 0.8); | |
| display: flex; | |
| justify-content: center; | |
| align-items: center; | |
| z-index: 9999; | |
| visibility: hidden; | |
| opacity: 0; | |
| transition: all 0.3s; | |
| } | |
| .loading-overlay.active { | |
| visibility: visible; | |
| opacity: 1; | |
| } | |
| .spinner { | |
| width: 60px; | |
| height: 60px; | |
| border: 6px solid var(--light-color); | |
| border-top: 6px solid var(--primary-color); | |
| border-radius: 50%; | |
| animation: spin 1s linear infinite; | |
| } | |
| @keyframes spin { | |
| 0% { transform: rotate(0deg); } | |
| 100% { transform: rotate(360deg); } | |
| } | |
| /* Empty state */ | |
| .empty-state { | |
| text-align: center; | |
| padding: 60px 20px; | |
| background-color: white; | |
| border-radius: 15px; | |
| box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08); | |
| } | |
| .empty-state i { | |
| font-size: 70px; | |
| color: #ddd; | |
| margin-bottom: 25px; | |
| } | |
| .empty-state h3 { | |
| color: var(--secondary-color); | |
| margin-bottom: 15px; | |
| font-weight: 600; | |
| } | |
| .empty-state p { | |
| color: #777; | |
| margin-bottom: 25px; | |
| font-size: 16px; | |
| } | |
| .empty-state .btn { | |
| padding: 12px 25px; | |
| border-radius: 10px; | |
| font-weight: 500; | |
| transition: all 0.3s ease; | |
| } | |
| .empty-state .btn:hover { | |
| transform: translateY(-3px); | |
| box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1); | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <!-- Loading Overlay --> | |
| <div class="loading-overlay" id="loadingOverlay"> | |
| <div class="spinner"></div> | |
| </div> | |
| <!-- Navbar --> | |
| <nav class="navbar navbar-expand-lg navbar-dark mb-4"> | |
| <div class="container"> | |
| <a class="navbar-brand" href="{{ url_for('index') }}"> | |
| <i class="fas fa-chart-line me-2"></i> لوحة إشارات التداول | |
| </a> | |
| <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav"> | |
| <span class="navbar-toggler-icon"></span> | |
| </button> | |
| <div class="collapse navbar-collapse" id="navbarNav"> | |
| <ul class="navbar-nav me-auto"> | |
| <li class="nav-item"> | |
| <a class="nav-link active" href="{{ url_for('index') }}"> | |
| <i class="fas fa-home me-1"></i> الرئيسية | |
| </a> | |
| </li> | |
| </ul> | |
| </div> | |
| </div> | |
| </nav> | |
| <div class="container"> | |
| <!-- Flash Messages --> | |
| {% with messages = get_flashed_messages(with_categories=true) %} | |
| {% if messages %} | |
| {% for category, message in messages %} | |
| <div class="alert alert-{{ category }} alert-dismissible fade show" role="alert"> | |
| {{ message }} | |
| <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button> | |
| </div> | |
| {% endfor %} | |
| {% endif %} | |
| {% endwith %} | |
| <!-- Dashboard Header --> | |
| <div class="dashboard-header"> | |
| <div class="row align-items-center"> | |
| <div class="col-md-6"> | |
| <h2 class="mb-0"><i class="fas fa-signal me-2"></i> إشارات التداول</h2> | |
| </div> | |
| <div class="col-md-6 text-md-end mt-3 mt-md-0"> | |
| <form action="{{ url_for('delete_all_signals') }}" method="post" id="deleteAllForm" class="d-inline"> | |
| <button type="button" class="delete-all-btn" onclick="confirmDeleteAll()"> | |
| <i class="fas fa-trash-alt me-1"></i> حذف جميع الإشارات | |
| </button> | |
| </form> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- System Status Cards --> | |
| <div class="row mb-4"> | |
| <div class="col-md-6 mb-3 mb-md-0"> | |
| <div class="card status-card h-100"> | |
| <div class="card-body"> | |
| <h5 class="card-title mb-4 fw-bold">النظام العميق</h5> | |
| <p class="card-text mb-4">الحالة الحالية: <strong>{{ 'نشط' if system_status.deeper else 'غير نشط' }}</strong></p> | |
| <div class="d-flex align-items-center justify-content-between"> | |
| <span class="fw-medium">تفعيل النظام:</span> | |
| <label class="switch"> | |
| <input type="checkbox" class="chbox" id="deeperToggle" {{ 'checked' if system_status.deeper else '' }} | |
| onchange="toggleSystem('deeper', this.checked)"> | |
| <div class="slider slider--0">تشغيل</div> | |
| <div class="slider slider--1"> | |
| <div></div> | |
| <div></div> | |
| </div> | |
| <div class="slider slider--2"></div> | |
| <div class="slider slider--3">إيقاف</div> | |
| </label> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="col-md-6"> | |
| <div class="card status-card h-100"> | |
| <div class="card-body"> | |
| <h5 class="card-title mb-4 fw-bold">النظام الرئيسي</h5> | |
| <p class="card-text mb-4">الحالة الحالية: <strong>{{ 'نشط' if system_status.paires else 'غير نشط' }}</strong></p> | |
| <div class="d-flex align-items-center justify-content-between"> | |
| <span class="fw-medium">تفعيل النظام:</span> | |
| <label class="switch"> | |
| <input type="checkbox" class="chbox" id="pairesToggle" {{ 'checked' if system_status.paires else '' }} | |
| onchange="toggleSystem('paires', this.checked)"> | |
| <div class="slider slider--0">تشغيل</div> | |
| <div class="slider slider--1"> | |
| <div></div> | |
| <div></div> | |
| </div> | |
| <div class="slider slider--2"></div> | |
| <div class="slider slider--3">إيقاف</div> | |
| </label> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Signals List --> | |
| <div class="signals-container"> | |
| {% if signals %} | |
| {% for signal in signals %} | |
| <div class="card signal-card"> | |
| <div class="card-header"> | |
| <div> | |
| <span class="me-2">{{ signal.pair }}</span> | |
| <span class="badge {{ 'badge-buy' if 'شراء' in signal.type else 'badge-sell' }}">{{ signal.type }}</span> | |
| </div> | |
| <div> | |
| <span class="badge | |
| {% if signal.status == 'starting' %}badge-starting | |
| {% elif signal.status == 'active' %}badge-active | |
| {% elif signal.status == 'completed' %}badge-completed | |
| {% elif signal.status == 'failed' %}badge-failed | |
| {% endif %}"> | |
| {% if signal.status == 'starting' %}بداية | |
| {% elif signal.status == 'active' %}نشط | |
| {% elif signal.status == 'completed' %}مكتمل | |
| {% elif signal.status == 'failed' %}فشل | |
| {% endif %} | |
| </span> | |
| </div> | |
| </div> | |
| <div class="card-body"> | |
| <div class="signal-info"> | |
| <div class="signal-detail"> | |
| <h6>الإطار الزمني</h6> | |
| <p>{{ signal.timeframe }}</p> | |
| </div> | |
| <div class="signal-detail"> | |
| <h6>نقطة الدخول</h6> | |
| <p>{{ signal.entry }}</p> | |
| </div> | |
| <div class="signal-detail"> | |
| <h6>وقف الخسارة</h6> | |
| <p>{{ signal.stop_loss }}</p> | |
| </div> | |
| <div class="signal-detail"> | |
| <h6>جني الأرباح</h6> | |
| <p>{{ signal.take_profit }}</p> | |
| </div> | |
| <div class="signal-detail"> | |
| <h6>المدة المتوقعة</h6> | |
| <p>{{ signal.duration }}</p> | |
| </div> | |
| </div> | |
| <div class="reason-section"> | |
| <h6>سبب التحليل</h6> | |
| <p>{{ signal.reason }}</p> | |
| </div> | |
| <div class="signal-actions"> | |
| <a href="{{ url_for('edit_signal', signal_id=loop.index0) }}" class="btn btn-primary btn-action"> | |
| <i class="fas fa-edit"></i> تعديل | |
| </a> | |
| <button type="button" class="btn btn-danger btn-action" | |
| onclick="confirmDelete({{ loop.index0 }})"> | |
| <i class="fas fa-trash-alt"></i> حذف | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| {% endfor %} | |
| {% else %} | |
| <div class="empty-state"> | |
| <i class="fas fa-chart-bar"></i> | |
| <h3>لا توجد إشارات متاحة</h3> | |
| <p>لا توجد إشارات تداول حالياً للعرض.</p> | |
| <a href="{{ url_for('add_signal') }}" class="btn btn-primary"> | |
| <i class="fas fa-plus me-1"></i> إضافة أول إشارة | |
| </a> | |
| </div> | |
| {% endif %} | |
| </div> | |
| </div> | |
| <!-- Add Signal Button --> | |
| <a href="{{ url_for('add_signal') }}" class="add-signal-btn"> | |
| <i class="fas fa-plus"></i> | |
| </a> | |
| <!-- Delete Signal Form (Hidden) --> | |
| <form id="deleteSignalForm" action="" method="post" style="display: none;"></form> | |
| <!-- Bootstrap JS and dependencies --> | |
| <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script> | |
| <!-- Custom JavaScript --> | |
| <script> | |
| // Show loading overlay | |
| function showLoading() { | |
| document.getElementById('loadingOverlay').classList.add('active'); | |
| } | |
| // Hide loading overlay | |
| function hideLoading() { | |
| document.getElementById('loadingOverlay').classList.remove('active'); | |
| } | |
| // Confirm delete signal | |
| function confirmDelete(signalId) { | |
| if (confirm('هل أنت متأكد من حذف هذه الإشارة؟')) { | |
| showLoading(); | |
| const form = document.getElementById('deleteSignalForm'); | |
| form.action = `/signals/delete/${signalId}`; | |
| form.submit(); | |
| } | |
| } | |
| // Confirm delete all signals | |
| function confirmDeleteAll() { | |
| if (confirm('هل أنت متأكد من حذف جميع الإشارات؟ لا يمكن التراجع عن هذا الإجراء!')) { | |
| showLoading(); | |
| document.getElementById('deleteAllForm').submit(); | |
| } | |
| } | |
| // Toggle system status | |
| function toggleSystem(systemType, status) { | |
| showLoading(); | |
| fetch('/system/toggle', { | |
| method: 'POST', | |
| headers: { | |
| 'Content-Type': 'application/x-www-form-urlencoded', | |
| }, | |
| body: `system_type=${systemType}&status=${status}` | |
| }) | |
| .then(response => response.json()) | |
| .then(data => { | |
| hideLoading(); | |
| if (data.success) { | |
| // Flash a success message | |
| let systemName = systemType === 'deeper' ? 'النظام العميق' : 'النظام الرئيسي'; | |
| let statusText = status ? 'تم تفعيل' : 'تم إيقاف'; | |
| const alertHtml = ` | |
| <div class="alert alert-success alert-dismissible fade show" role="alert"> | |
| ${statusText} ${systemName} بنجاح! | |
| <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button> | |
| </div> | |
| `; | |
| document.querySelector('.container').insertAdjacentHTML('afterbegin', alertHtml); | |
| } else { | |
| alert(`خطأ: ${data.message}`); | |
| // Reset the toggle to its previous state | |
| document.getElementById(`${systemType}Toggle`).checked = !status; | |
| } | |
| }) | |
| .catch(error => { | |
| hideLoading(); | |
| console.error('Error:', error); | |
| alert('حدث خطأ أثناء تحديث حالة النظام.'); | |
| // Reset the toggle to its previous state | |
| document.getElementById(`${systemType}Toggle`).checked = !status; | |
| }); | |
| } | |
| // Auto-dismiss alerts after 5 seconds | |
| document.addEventListener('DOMContentLoaded', function() { | |
| setTimeout(function() { | |
| const alerts = document.querySelectorAll('.alert'); | |
| alerts.forEach(alert => { | |
| const bsAlert = new bootstrap.Alert(alert); | |
| bsAlert.close(); | |
| }); | |
| }, 5000); | |
| }); | |
| </script> | |
| </body> | |
| </html> |