last_edit / frontend /competitor-intel.html
Moharek
Deploy Moharek GEO Platform
a74b879
<!doctype html>
<html lang="ar" dir="rtl">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<title>محلل المنافسين الذكي — Moharek GEO Platform</title>
<link href="https://fonts.googleapis.com/css2?family=Cairo:wght@400;600;700;800&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>
/* Animated Page Specific Elements */
.header-card{position:relative;overflow:hidden;background:linear-gradient(165deg,rgba(7,31,33,0.9),rgba(5,7,10,0.95))}
.header-card::before{content:'';position:absolute;inset:0;background:radial-gradient(circle at top right,rgba(200,240,78,0.1),transparent);pointer-events:none}
.reveal{opacity:0;transform:translateY(20px);transition:all .6s cubic-bezier(.16,1,.3,1)}
.reveal.show{opacity:1;transform:translateY(0)}
</style>
</head>
<body>
<div class="bg-mesh"></div>
<div class="bg-grid"></div>
<nav>
<div class="nav-inner">
<a href="/portal.html" class="nav-logo">
<div class="logo-box" style="width:40px;height:40px;display:grid;place-items:center;overflow:hidden;border-radius:10px;background:transparent">
<img src="moharek-logo-v2.svg" alt="Moharek" style="width:100%;height:100%;object-fit:contain">
</div>
<div>
<div style="font-size:15px;font-weight:900;color:#fff">محرك GEO</div>
<div style="font-size:10px;color:var(--text-muted);font-weight:500">COMPETITOR INTEL · AI</div>
</div>
</a>
<div class="nav-links">
<a class="nav-link" href="/portal.html">لوحة التحكم</a>
<a class="nav-link" href="/jobs.html">المهام</a>
<a class="nav-link active" href="/competitor-intel.html">الذكاء</a>
<a class="nav-link" href="/actions.html">النمو</a>
<a class="nav-link" href="/ads.html">الإعلانات</a>
</div>
</div>
</nav>
<style>
/* Professional Navbar Styles (Sync with search.html) */
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}
.nav-logo{display:flex;align-items:center;gap:12px;text-decoration:none}
.logo-box { width: 44px; height: 40px; position: relative; }
.gear-motif i { position: absolute; font-size: 18px; animation: gearSpin 10s linear infinite; }
.gear-blue { top: 0; left: 50%; translate: -50% 0; color: var(--accent2); }
.gear-gold { bottom: 2px; left: 4px; color: var(--accent); font-size: 14px!important; animation-delay: -3s!important; }
.gear-red { bottom: 2px; right: 4px; color: var(--danger); font-size: 14px!important; animation-delay: -6s!important; }
@keyframes gearSpin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }
.nav-links{display:flex;gap:28px}
.nav-link{color:var(--text-muted);text-decoration:none;font-weight:700;font-size:14px;transition:.3s}
.nav-link:hover, .nav-link.active{color:#fff}
</style>
<div class="wrap" style="padding-top:40px;max-width:1200px;margin:0 auto">
<div class="header-card glass reveal" style="text-align:center;padding:60px 24px;border-radius:32px;margin-bottom:40px">
<div class="badge badge-info" style="margin-bottom:16px"><i class="fas fa-search-plus"></i> وكيل ذكاء المنافسين</div>
<h1 class="hero-title" style="margin-bottom:12px">محلل المنافسين الذكي v2</h1>
<p class="hero-subtitle" style="margin-bottom:24px">اكتشف منافسيك الحقيقيين + Scoring System + AI Insights محددة</p>
<div style="display:flex;gap:12px;justify-content:center;flex-wrap:wrap">
<span class="badge badge-success"><i class="fas fa-bolt"></i> Google PageSpeed</span>
<span id="serp-badge" class="badge badge-warning"><i class="fas fa-database"></i> SerpAPI</span>
<span id="ai-badge" class="badge badge-warning"><i class="fas fa-brain"></i> Groq AI</span>
</div>
</div>
<div class="input-box glass reveal" style="margin-bottom:32px">
<h2 class="card-title"><i class="fas fa-cog"></i> إعداد التحليل</h2>
<p class="card-desc">أدخل موقعك وحدد المنطقة للعثور على منافسيك الحقيقيين</p>
<div class="input-row">
<div style="flex:2">
<label class="stat-label" style="display:block;margin-bottom:8px">رابط موقعك</label>
<input id="yourUrl" type="url" placeholder="https://rabhanagency.com" style="width:100%"/>
</div>
<div style="flex:1">
<label class="stat-label" style="display:block;margin-bottom:8px">المنطقة المستهدفة</label>
<select id="region" style="width:100%">
<option value="Saudi Arabia">السعودية 🇸🇦</option>
<option value="Egypt">مصر 🇪🇬</option>
<option value="Global">عالمي 🌍</option>
</select>
</div>
</div>
<div class="input-row" style="margin-top:20px">
<div style="flex:1">
<label class="stat-label" style="display:block;margin-bottom:8px">المجال / النيش</label>
<input id="industry" placeholder="مثال: تسويق رقمي" style="width:100%"/>
</div>
<div style="flex:none;width:150px">
<label class="stat-label" style="display:block;margin-bottom:8px">العدد</label>
<select id="count" style="width:100%">
<option value="5">5</option>
<option value="7" selected>7</option>
<option value="10">10</option>
</select>
</div>
<div style="flex:none;display:flex;align-items:flex-end">
<button class="btn btn-primary" id="analyzeBtn" onclick="runAnalysis()" style="height:48px;padding:0 40px">تشغيل التحليل</button>
</div>
</div>
</div>
<div id="results" style="display:none">
<div class="card glass reveal" style="margin-bottom:32px">
<div style="display:flex;justify-content:space-between;align-items:flex-start">
<div>
<div class="badge badge-info" style="margin-bottom:8px">نطاقك</div>
<div id="yourDomain" class="hero-title" style="font-size:24px;margin-bottom:0"></div>
</div>
<div style="text-align:left">
<div id="yourScore" class="stat-value" style="font-size:48px"></div>
<div id="yourRank" class="stat-label"></div>
</div>
</div>
<div id="yourSpeed" class="grid-4" style="margin-top:24px"></div>
<div id="yourVitals" style="display:flex;gap:10px;flex-wrap:wrap;margin-top:16px"></div>
</div>
<div id="status" style="margin-top:16px;font-size:14px;color:var(--text-muted);text-align:center"></div>
<div style="display:flex;gap:12px;margin:24px 0 16px;flex-wrap:wrap">
<button class="btn btn-sm btn-accent" data-seg="all" onclick="filterSegment('all')">الكل</button>
<button class="btn btn-sm btn-secondary" data-seg="direct" onclick="filterSegment('direct')"> منافسون مباشرون</button>
<button class="btn btn-sm btn-secondary" data-seg="indirect" onclick="filterSegment('indirect')"> غير مباشرين</button>
<button class="btn btn-sm btn-secondary" data-seg="aspirational" onclick="filterSegment('aspirational')"> علامات كبرى</button>
</div>
<h2 class="section-title" style="margin-bottom:4px">
المنافسون المكتشفون <span id="compCount" style="color:var(--primary);font-size:16px"></span>
</h2>
<p style="color:var(--text-muted);font-size:13px;margin-bottom:0" id="dataSourceNote"></p>
<div class="grid-3" id="compGrid"></div>
<div class="card stagger-item" id="aiCard" style="display:none;margin-top:24px">
<h3 class="section-title" style="margin-top:0"> التحليل الاستراتيجي بالذكاء الاصطناعي</h3>
<div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(300px,1fr));gap:20px" id="aiGrid"></div>
<div id="aiSummary" style="margin-top:16px;padding:16px;background:var(--bg-elevated);border-radius:12px;font-size:14px;color:var(--text-muted);line-height:1.7;border:1px solid var(--border)"></div>
</div>
</div>
</div>
<script>
// Auto-fill from localStorage if coming from homepage
const lastUrl = localStorage.getItem('lastJobUrl');
if (lastUrl) {
document.getElementById('yourUrl').value = lastUrl;
}
const storedKeys = JSON.parse(localStorage.getItem('geo_keys') || '{}');
if (storedKeys.serpapi || storedKeys.serp) {
document.getElementById('serp-badge').className = 'source-badge source-active';
document.getElementById('serp-badge').textContent = ' SerpAPI — متصل';
}
if (storedKeys.groq || storedKeys.openai) {
document.getElementById('ai-badge').className = 'source-badge source-active';
document.getElementById('ai-badge').textContent = ' AI — متصل';
}
let currentData = null;
let currentSegment = 'all';
function scoreColor(s) {
if (s === null || s === undefined) return 'var(--text-dim)';
return s >= 80 ? 'var(--success)' : s >= 50 ? 'var(--accent)' : 'var(--danger)';
}
function renderSpeedGrid(ps, containerId, vitalsId) {
const el = document.getElementById(containerId);
const vitalsEl = document.getElementById(vitalsId);
if (!ps) { el.innerHTML = '<div style="color:var(--text-muted);font-size:13px">جارٍ تحميل...</div>'; return; }
const metrics = [
{ label: 'الأداء', val: ps.performance },
{ label: 'SEO', val: ps.seo },
{ label: 'وصول', val: ps.accessibility },
];
el.innerHTML = metrics.map(m => `
<div style="text-align:center">
<span style="color:${scoreColor(m.val)};font-size:22px;font-weight:900;display:block;margin-bottom:2px">${m.val ?? '—'}</span>
<span style="font-size:10px;color:var(--text-muted);text-transform:uppercase">${m.label}</span>
</div>`).join('');
vitalsEl.innerHTML = [['FCP', ps.fcp], ['LCP', ps.lcp], ['CLS', ps.cls], ['TBT', ps.tbt]]
.map(([k, v]) => `<span class="badge" style="background:var(--bg-elevated);color:var(--text-muted);border:1px solid var(--border)">${k}: ${v}</span>`).join('');
}
function filterSegment(seg) {
currentSegment = seg;
document.querySelectorAll('.seg-tab').forEach(t => t.classList.remove('active'));
document.querySelector(`[data-seg="${seg}"]`).classList.add('active');
if (currentData) renderCompetitors(currentData.competitors, seg);
}
function renderCompetitors(competitors, segment = 'all') {
const grid = document.getElementById('compGrid');
grid.innerHTML = '';
let filtered = competitors;
if (segment !== 'all') {
filtered = competitors.filter(c => (c.competitor_type || 'Direct').toLowerCase() === segment.toLowerCase());
}
if (filtered.length === 0) {
grid.innerHTML = '<div style="color:var(--text-muted);padding:40px;text-align:center;grid-column:1/-1">لا يوجد منافسون في هذه الفئة</div>';
return;
}
filtered.forEach((c, i) => {
const ps = c.pagespeed || {};
const score = c.score || {};
const typeClass = `type-${(c.competitor_type || 'direct').toLowerCase()}`;
const typeLabel = { 'Direct': 'مباشر', 'Indirect': 'غير مباشر', 'Aspirational': 'علامة كبرى' }[c.competitor_type] || 'مباشر';
const card = document.createElement('div');
card.className = 'card stagger-item';
card.style.animationDelay = `${i * 0.05}s`;
card.style.position = 'relative';
card.innerHTML = `
<div style="position:absolute;top:16px;left:16px;width:32px;height:32px;border-radius:8px;background:linear-gradient(135deg,var(--primary),var(--primary-light));color:#fff;font-weight:700;font-size:14px;display:flex;align-items:center;justify-content:center">${c.serp_position || i + 1}</div>
<div class="badge badge-info" style="position:absolute;top:16px;right:16px">${typeLabel}</div>
<div style="font-weight:800;font-size:16px;margin-bottom:6px;padding-right:8px;margin-top:24px;color:var(--text)">${c.domain}</div>
<div style="font-size:12px;color:var(--text-muted);line-height:1.6;margin-bottom:16px">${c.snippet || c.title || ''}</div>
<div style="font-size:28px;font-weight:900;margin:12px 0 8px;text-align:center;color:${scoreColor(score.total)}">${score.total || '—'}</div>
<div style="text-align:center;font-size:11px;color:var(--text-muted);text-transform:uppercase;letter-spacing:1px">تقييم ${score.grade || '?'}</div>
<div style="display:grid;grid-template-columns:1fr 1fr 1fr;gap:8px;margin-top:16px">
${[['SEO', ps.seo], ['أداء', ps.performance], ['وصول', ps.accessibility]].map(([l, v]) => `
<div style="text-align:center">
<span style="color:${scoreColor(v)};font-size:18px;font-weight:900;display:block;margin-bottom:2px">${v ?? '—'}</span>
<span style="font-size:10px;color:var(--text-muted);text-transform:uppercase">${l}</span>
</div>`).join('')}
</div>
<div style="display:flex;gap:8px;flex-wrap:wrap;margin-top:12px">
${[['FCP', ps.fcp], ['LCP', ps.lcp], ['CLS', ps.cls]].map(([k, v]) => `<span class="badge" style="background:var(--bg-elevated);color:var(--text-muted);border:1px solid var(--border)">${k}: ${v}</span>`).join('')}
</div>
<div style="margin-top:16px;text-align:center">
<a href="https://${c.domain}" target="_blank" style="font-size:13px;color:var(--primary);text-decoration:none;font-weight:600">زيارة الموقع ↗</a>
</div>`;
grid.appendChild(card);
});
}
function renderAIAnalysis(insights) {
if (!insights || !insights.market_summary) return;
document.getElementById('aiCard').style.display = 'block';
const grid = document.getElementById('aiGrid');
const sections = [
{ title: ' موقعك في السوق', items: [insights.market_position || 'Challenger'] },
{ title: ' نقاط قوتك', items: insights.your_strengths || [] },
{ title: ' نقاط ضعفك', items: insights.your_weaknesses || [] },
{ title: ' انتصارات سريعة', items: (insights.quick_wins || []).map(w => w.win || w) },
{ title: ' فرص ذهبية', items: (insights.opportunities || []).map(o => o.action || o) },
{ title: ' تهديدات', items: (insights.direct_threats || []).map(t => `${t.competitor}: ${t.threat}`) },
];
grid.innerHTML = sections.map(s => {
const items = Array.isArray(s.items)
? s.items.map(v => `<div style="font-size:13px;color:var(--text-muted);padding:8px 12px;background:var(--bg-elevated);border-radius:8px;margin-bottom:6px;border-right:3px solid var(--primary);line-height:1.6">${v}</div>`).join('')
: `<div style="font-size:16px;font-weight:800;color:var(--primary);padding:8px 12px;background:var(--bg-elevated);border-radius:8px;border-right:3px solid var(--primary)">${s.items}</div>`;
return `<div style="margin-bottom:20px"><h4 style="font-size:14px;font-weight:700;color:var(--text);margin-bottom:10px">${s.title}</h4>${items}</div>`;
}).join('');
if (insights.market_summary) {
document.getElementById('aiSummary').innerHTML = `<strong style="color:var(--text)">ملخص السوق:</strong> ${insights.market_summary}`;
}
}
async function runAnalysis() {
const url = document.getElementById('yourUrl').value.trim();
if (!url) { document.getElementById('status').textContent = 'أدخل رابط موقعك أولاً'; return; }
const btn = document.getElementById('analyzeBtn');
const status = document.getElementById('status');
btn.disabled = true;
btn.textContent = '⏳ جارٍ التحليل...';
document.getElementById('results').style.display = 'none';
status.innerHTML = '<span class="shine-text">⏳ جارٍ البحث عن المنافسين وقياس الأداء...</span>';
try {
const keys = JSON.parse(localStorage.getItem('geo_keys') || '{}');
const resp = await fetch('http://localhost:8001/api/competitor/intelligence', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
url, region: document.getElementById('region').value,
industry: document.getElementById('industry').value,
count: parseInt(document.getElementById('count').value),
api_keys: keys
})
});
const data = await resp.json();
if (!data.ok) { status.textContent = ' خطأ: ' + data.error; btn.disabled = false; btn.textContent = ' تحليل المنافسين'; return; }
const r = data.result;
currentData = r;
status.innerHTML = `<span style="color:var(--success)"> تم اكتشاف ${r.competitor_count} منافس</span>`;
const note = [];
if (r.data_sources.serp) note.push(' SerpAPI: نتائج حقيقية من Google');
else note.push(' بدون SerpAPI: المنافسون مقترحون بالذكاء الاصطناعي');
if (r.data_sources.pagespeed) note.push(' PageSpeed: بيانات أداء حقيقية');
if (r.data_sources.ai) note.push(' AI: تحليل استراتيجي حقيقي');
else note.push(' أضف Groq API للتحليل الاستراتيجي');
document.getElementById('dataSourceNote').textContent = note.join(' · ');
document.getElementById('yourDomain').textContent = r.your_domain;
document.getElementById('yourScore').textContent = r.your_score?.total || '?';
document.getElementById('yourRank').textContent = `#${r.your_rank || '?'} في ${r.competitor_count + 1} مواقع · ${r.market_position || 'Challenger'}`;
renderSpeedGrid(r.your_pagespeed, 'yourSpeed', 'yourVitals');
document.getElementById('compCount').textContent = ` (${r.competitor_count})`;
renderCompetitors(r.competitors, 'all');
renderAIAnalysis(r.insights);
document.getElementById('results').style.display = 'block';
} catch (e) {
status.textContent = ' فشل الطلب: ' + e.message;
} finally {
btn.disabled = false;
btn.textContent = ' تحليل المنافسين';
}
}
document.getElementById('yourUrl').addEventListener('keydown', e => { if (e.key === 'Enter') runAnalysis(); });
// Handle Reveal Animations
const observerOptions = { threshold: 0.1, rootMargin: '0px 0px -50px 0px' };
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.classList.add('show');
observer.unobserve(entry.target);
}
});
}, observerOptions);
window.addEventListener('DOMContentLoaded', () => {
document.querySelectorAll('.reveal').forEach(el => observer.observe(el));
});
</script>
</body>
</html>