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> |