| <!DOCTYPE html> |
| <html lang="ar" dir="rtl"> |
| <head> |
| <meta charset="utf-8"/> |
| <meta name="viewport" content="width=device-width,initial-scale=1"/> |
| <title>خطة النمو — محرك</title> |
| <link href="https://fonts.googleapis.com/css2?family=Cairo:wght@400;500;600;700;800;900&display=swap" rel="stylesheet"> |
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.0/css/all.min.css"> |
| <link rel="stylesheet" href="/theme.css"> |
| <style> |
| |
| .wrap{max-width:1200px;margin:0 auto;padding:40px 24px} |
| nav{position:sticky;top:0;z-index:1000;border-bottom:1px solid var(--border);background:rgba(7,31,33,.85);backdrop-filter:blur(32px);height:80px;display:flex;align-items:center} |
| .nav-inner{max-width:1200px;margin:0 auto;padding:0 32px;width:100%;display:flex;justify-content:space-between;align-items:center} |
| .logo{display:flex;align-items:center;gap:12px;font-weight:900;font-size:18px;text-decoration:none;color:#fff} |
| .logo-icon{width:40px;height:40px;background:linear-gradient(135deg,#c8f04e,#5fd4dc);border-radius:10px;display:flex;align-items:center;justify-content:center;font-size:20px;color:#000} |
| .nav-links{display:flex;gap:28px} |
| .nav-link{color:var(--text-muted);text-decoration:none;font-weight:700;font-size:14px;transition:.3s;padding:8px;position:relative} |
| .nav-link:hover{color:#fff} |
| .nav-link.active{color:var(--text)} |
| .nav-link.active::after{content:'';position:absolute;bottom:-10px;left:0;right:0;height:2px;background:var(--accent);border-radius:2px} |
| .bg-pattern{position:fixed;inset:0;z-index:-1;background:radial-gradient(circle at 10% 10%,rgba(95,212,220,.1) 0%,transparent 45%),radial-gradient(circle at 90% 90%,rgba(200,240,78,.08) 0%,transparent 45%);filter:blur(120px)} |
| |
| |
| .action-card{background:var(--bg-elevated);border:1px solid var(--border);border-radius:12px;padding:18px;margin-bottom:12px;display:flex;align-items:flex-start;gap:14px;transition:all 0.25s ease} |
| .action-card:hover{border-color:rgba(16,185,129,0.3);transform:translateY(-2px)} |
| .action-card.done{opacity:0.5;border-color:rgba(16,185,129,0.2)} |
| .action-ico{width:38px;height:38px;border-radius:10px;display:grid;place-items:center;font-size:14px;flex-shrink:0} |
| .action-body{flex:1;min-width:0} |
| .action-task{font-size:13.5px;font-weight:700;margin-bottom:4px;line-height:1.4} |
| .action-meta{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-bottom:8px} |
| .action-details{background:rgba(255,255,255,0.02);border-radius:8px;padding:12px;margin-top:8px;border-left:3px solid rgba(16,185,129,0.3)} |
| .detail-item{font-size:11px;color:var(--text-muted);margin-bottom:4px;line-height:1.4} |
| .detail-item:last-child{margin-bottom:0} |
| .detail-item strong{color:var(--text);font-weight:600} |
| .pri-badge{padding:2px 9px;border-radius:5px;font-size:10px;font-weight:800} |
| .pri-high{background:rgba(239,68,68,0.15);color:#ef4444} |
| .pri-medium{background:rgba(251,191,36,0.15);color:#fbbf24} |
| .pri-low{background:rgba(16,185,129,0.15);color:#10b981} |
| .status-badge{padding:2px 9px;border-radius:5px;font-size:10px;font-weight:700} |
| .status-pending{background:rgba(148,163,184,0.15);color:#94a3b8} |
| .status-done{background:rgba(16,185,129,0.15);color:#10b981} |
| .status-running{background:rgba(59,130,246,0.15);color:#3b82f6} |
| .impact-badge{padding:2px 8px;border-radius:4px;font-size:9px;font-weight:600} |
| .impact-high{background:rgba(239,68,68,0.1);color:#ef4444;border:1px solid rgba(239,68,68,0.2)} |
| .impact-medium{background:rgba(251,191,36,0.1);color:#fbbf24;border:1px solid rgba(251,191,36,0.2)} |
| .impact-low{background:rgba(148,163,184,0.1);color:#94a3b8;border:1px solid rgba(148,163,184,0.2)} |
| .effort-badge{padding:2px 8px;border-radius:4px;font-size:9px;font-weight:600} |
| .effort-low{background:rgba(16,185,129,0.1);color:#10b981;border:1px solid rgba(16,185,129,0.2)} |
| .effort-medium{background:rgba(251,191,36,0.1);color:#fbbf24;border:1px solid rgba(251,191,36,0.2)} |
| .effort-high{background:rgba(239,68,68,0.1);color:#ef4444;border:1px solid rgba(239,68,68,0.2)} |
| .timeline-badge{padding:2px 8px;border-radius:4px;font-size:9px;font-weight:600;background:rgba(59,130,246,0.1);color:#3b82f6;border:1px solid rgba(59,130,246,0.2)} |
| .exec-btn{padding:7px 14px;border-radius:8px;font-size:11.5px;font-weight:700;border:1px solid var(--border);background:transparent;color:var(--text-muted);cursor:pointer;font-family:'Cairo',sans-serif;transition:all 0.2s;white-space:nowrap} |
| .exec-btn:hover{background:rgba(16,185,129,0.1);border-color:rgba(16,185,129,0.4);color:#10b981} |
| .filter-tabs{display:flex;gap:8px;margin-bottom:20px;flex-wrap:wrap} |
| .ftab{padding:7px 16px;border-radius:8px;font-size:12px;font-weight:700;border:1px solid var(--border);background:transparent;color:var(--text-muted);cursor:pointer;font-family:'Cairo',sans-serif;transition:all 0.2s} |
| .ftab.on{background:rgba(16,185,129,0.12);border-color:rgba(16,185,129,0.35);color:#10b981} |
| .stats-row{display:grid;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));gap:12px;margin-bottom:24px} |
| .stat-mini{background:var(--bg-elevated);border:1px solid var(--border);border-radius:12px;padding:16px;text-align:center} |
| .stat-mini-num{font-size:26px;font-weight:900;line-height:1;margin-bottom:4px} |
| .stat-mini-lbl{font-size:11.5px;color:var(--text-muted);font-weight:500} |
| </style> |
| </head> |
| <body> |
| <div class="bg-pattern"></div> |
| <nav> |
| <div class="nav-inner"> |
| <div class="logo"><div class="logo-icon">⚡</div>محرك</div> |
| <div class="nav-links"> |
| <a class="nav-link" href="/portal.html"><i class="fas fa-th-large"></i> الرئيسية</a> |
| <a class="nav-link" href="/jobs.html"><i class="fas fa-satellite-dish"></i> التحليلات</a> |
| <a class="nav-link active" href="/actions.html"><i class="fas fa-bolt"></i> خطة النمو</a> |
| </div> |
| <button class="btn btn-secondary btn-sm" onclick="logout()">خروج</button> |
| </div> |
| </nav> |
|
|
| <div class="wrap" style="padding-top:32px;padding-bottom:64px"> |
| <div style="display:flex;align-items:flex-start;justify-content:space-between;margin-bottom:24px;flex-wrap:wrap;gap:14px"> |
| <div> |
| <h1 style="font-size:24px;font-weight:900;margin-bottom:6px">خطة النمو الفورية</h1> |
| <p style="color:var(--text-muted);font-size:13px">إجراءات مرتبة حسب الأثر — نفّذها خطوة بخطوة لرفع ظهورك</p> |
| </div> |
| <button class="btn btn-primary" onclick="loadActions()"><i class="fas fa-sync-alt"></i> تحديث</button> |
| </div> |
|
|
| <div class="stats-row" id="statsRow"> |
| <div class="stat-mini"><div class="stat-mini-num" id="stTotal" style="color:#3b82f6">0</div><div class="stat-mini-lbl">إجمالي الإجراءات</div></div> |
| <div class="stat-mini"><div class="stat-mini-num" id="stHigh" style="color:#ef4444">0</div><div class="stat-mini-lbl">أولوية عالية</div></div> |
| <div class="stat-mini"><div class="stat-mini-num" id="stPending" style="color:#fbbf24">0</div><div class="stat-mini-lbl">قيد الانتظار</div></div> |
| <div class="stat-mini"><div class="stat-mini-num" id="stDone" style="color:#10b981">0</div><div class="stat-mini-lbl">مكتمل</div></div> |
| </div> |
|
|
| <div class="filter-tabs"> |
| <button class="ftab on" onclick="filterActions('all',this)">الكل</button> |
| <button class="ftab" onclick="filterActions('high',this)">🔴 عالية</button> |
| <button class="ftab" onclick="filterActions('medium',this)">🟡 متوسطة</button> |
| <button class="ftab" onclick="filterActions('low',this)">🟢 منخفضة</button> |
| <button class="ftab" onclick="filterActions('pending',this)">⏳ قيد الانتظار</button> |
| <button class="ftab" onclick="filterActions('done',this)">✅ مكتمل</button> |
| </div> |
|
|
| <div id="actionsList"> |
| <div style="text-align:center;padding:48px;color:var(--text-muted)"> |
| <i class="fas fa-circle-notch fa-spin" style="font-size:24px;margin-bottom:12px;display:block"></i> |
| جاري تحميل خطة العمل... |
| </div> |
| </div> |
| </div> |
|
|
| <script> |
| const token = localStorage.getItem('token'); |
| |
| |
| let allActions = []; |
| let currentFilter = 'all'; |
| |
| async function loadActions(){ |
| try{ |
| const r = await fetch('/api/actions/list',{headers:{Authorization:`Bearer ${token}`}}); |
| const d = await r.json(); |
| if(!d.ok) throw new Error(d.error); |
| allActions = d.actions||[]; |
| updateStats(); |
| renderActions(); |
| }catch(e){ |
| document.getElementById('actionsList').innerHTML=`<div class="alert alert-error">❌ ${e.message}</div>`; |
| } |
| } |
| |
| function updateStats(){ |
| document.getElementById('stTotal').textContent = allActions.length; |
| document.getElementById('stHigh').textContent = allActions.filter(a=>a.priority_score>=80).length; |
| document.getElementById('stPending').textContent = allActions.filter(a=>a.status==='pending').length; |
| document.getElementById('stDone').textContent = allActions.filter(a=>a.status==='done'||a.status==='completed').length; |
| } |
| |
| function filterActions(f, btn){ |
| currentFilter = f; |
| document.querySelectorAll('.ftab').forEach(t=>t.classList.remove('on')); |
| btn.classList.add('on'); |
| renderActions(); |
| } |
| |
| function renderActions(){ |
| let list = allActions; |
| if(currentFilter==='high') list=list.filter(a=>a.priority_score>=80); |
| else if(currentFilter==='medium') list=list.filter(a=>a.priority_score>=40&&a.priority_score<80); |
| else if(currentFilter==='low') list=list.filter(a=>a.priority_score<40); |
| else if(currentFilter==='pending') list=list.filter(a=>a.status==='pending'); |
| else if(currentFilter==='done') list=list.filter(a=>a.status==='done'||a.status==='completed'); |
| |
| if(!list.length){ |
| document.getElementById('actionsList').innerHTML=` |
| <div style="text-align:center;padding:48px;color:var(--text-muted)"> |
| <i class="fas fa-check-circle" style="font-size:32px;color:#10b981;margin-bottom:12px;display:block"></i> |
| لا توجد إجراءات في هذه الفئة |
| </div>`; |
| return; |
| } |
| |
| document.getElementById('actionsList').innerHTML = list.map(a=>{ |
| const pri = a.priority_score>=80?'high':a.priority_score>=40?'medium':'low'; |
| const priLabel = pri==='high'?'عالية':pri==='medium'?'متوسطة':'منخفضة'; |
| const icoColor = pri==='high'?'#ef4444':pri==='medium'?'#fbbf24':'#10b981'; |
| const icoBg = pri==='high'?'rgba(239,68,68,0.12)':pri==='medium'?'rgba(251,191,36,0.12)':'rgba(16,185,129,0.12)'; |
| const ico = a.type==='content'?'fa-file-alt':a.type==='technical'?'fa-cog':a.type==='keywords'?'fa-key':a.type==='ai_visibility'?'fa-brain':a.type==='strategy'?'fa-chess':a.type==='authority'?'fa-crown':'fa-bolt'; |
| const isDone = a.status==='done'||a.status==='completed'; |
| |
| |
| const hasDetails = a.impact || a.effort || a.timeline || a.current_state; |
| |
| return ` |
| <div class="action-card ${isDone?'done':''}" id="ac-${a.id}"> |
| <div class="action-ico" style="background:${icoBg};color:${icoColor}"><i class="fas ${ico}"></i></div> |
| <div class="action-body"> |
| <div class="action-task">${a.task||'إجراء غير محدد'}</div> |
| <div class="action-meta"> |
| <span class="pri-badge pri-${pri}">${priLabel}</span> |
| <span class="status-badge status-${a.status||'pending'}">${a.status==='done'||a.status==='completed'?'✅ مكتمل':a.status==='running'?'⚡ جاري':'⏳ انتظار'}</span> |
| ${a.job_id?`<span style="font-size:10.5px;color:var(--text-muted)">مهمة #${a.job_id}</span>`:''} |
| ${a.impact?`<span class="impact-badge impact-${a.impact}">${a.impact==='high'?'تأثير عالي':a.impact==='medium'?'تأثير متوسط':'تأثير منخفض'}</span>`:''} |
| ${a.effort?`<span class="effort-badge effort-${a.effort}">${a.effort==='low'?'جهد قليل':a.effort==='medium'?'جهد متوسط':'جهد كبير'}</span>`:''} |
| ${a.timeline?`<span class="timeline-badge">⏱️ ${a.timeline}</span>`:''} |
| </div> |
| ${hasDetails?` |
| <div class="action-details"> |
| ${a.current_state?`<div class="detail-item"><strong>الحالة الحالية:</strong> ${a.current_state}</div>`:''} |
| ${a.target_state?`<div class="detail-item"><strong>الهدف:</strong> ${a.target_state}</div>`:''} |
| ${a.expected_result?`<div class="detail-item"><strong>النتيجة المتوقعة:</strong> ${a.expected_result}</div>`:''} |
| ${a.specific_url?`<div class="detail-item"><strong>الصفحة:</strong> <a href="${a.specific_url}" target="_blank" style="color:#10b981;text-decoration:none">${a.specific_url}</a></div>`:''} |
| </div> |
| `:''} |
| ${a.result?`<div style="font-size:11.5px;color:#94a3b8;margin-top:6px;padding:8px;background:rgba(255,255,255,0.02);border-radius:6px">${a.result}</div>`:''} |
| </div> |
| ${!isDone?`<button class="exec-btn" onclick="executeAction(${a.id})" title="تنفيذ هذا الإجراء"><i class="fas fa-play"></i> تنفيذ</button>`:''} |
| </div>`; |
| }).join(''); |
| } |
| |
| async function executeAction(id){ |
| const card = document.getElementById('ac-'+id); |
| const btn = card?.querySelector('.exec-btn'); |
| if(btn){ btn.innerHTML='<i class="fas fa-circle-notch fa-spin"></i>'; btn.disabled=true; } |
| try{ |
| const r = await fetch(`/api/actions/${id}/execute`,{ |
| method:'POST', |
| headers:{Authorization:`Bearer ${token}`} |
| }); |
| const d = await r.json(); |
| if(d.ok){ |
| const a = allActions.find(x=>x.id===id); |
| if(a) a.status='running'; |
| updateStats(); |
| renderActions(); |
| } |
| }catch(e){ alert('خطأ: '+e.message); } |
| finally{ |
| if(btn){ btn.innerHTML='<i class="fas fa-play"></i> تنفيذ'; btn.disabled=false; } |
| } |
| } |
| |
| function logout(){localStorage.clear();window.location.href='/login.html'} |
| loadActions(); |
| </script> |
| </body> |
| </html> |
|
|