Files
wevia-brain/s89-arsenal-screens/scrapping-factory-enhanced.html
2026-04-12 23:01:36 +02:00

209 lines
18 KiB
HTML
Executable File

<?php include_once("/opt/wevads-arsenal/public/api/wevads-metrics.php"); ?>
<?php
$_db=new PDO('pgsql:host=localhost;dbname=adx_system','admin','admin123');
$_db->exec('SET search_path TO admin');
$_sf_total=(int)$_db->query("SELECT COUNT(*) FROM scrapping_results")->fetchColumn();
$_sf_valid=(int)$_db->query("SELECT COUNT(*) FROM scrapping_results WHERE is_verified=true")->fetchColumn();
$_sf_enriched=(int)$_db->query("SELECT COUNT(*) FROM scrapping_results WHERE full_name IS NOT NULL AND full_name!='' AND full_name LIKE '% %'")->fetchColumn();
$_sf_withCompany=(int)$_db->query("SELECT COUNT(*) FROM scrapping_results WHERE company IS NOT NULL AND company!=''")->fetchColumn();
$_sf_withLoc=(int)$_db->query("SELECT COUNT(*) FROM scrapping_results WHERE location IS NOT NULL AND location!=''")->fetchColumn();
$_sf_inCRM=(int)$_db->query("SELECT COUNT(*) FROM scrapping_results sr WHERE EXISTS (SELECT 1 FROM leads l WHERE l.email=sr.email)")->fetchColumn();
$_sf_jobs=(int)$_db->query("SELECT COUNT(*) FROM dark_scraper_jobs")->fetchColumn();
$_sf_targets=(int)$_db->query("SELECT COUNT(*) FROM scraping_targets WHERE status='active'")->fetchColumn();
$_sf_linkedin=(int)$_db->query("SELECT COUNT(*) FROM scrapping_results WHERE source_url LIKE '%linkedin%'")->fetchColumn();
$_isps=$_db->query("SELECT COALESCE(revenue_range,'Other') as isp, COUNT(*) as c FROM scrapping_results GROUP BY revenue_range ORDER BY c DESC LIMIT 10")->fetchAll(PDO::FETCH_ASSOC);
$_countries=$_db->query("SELECT COALESCE(location,'Unknown') as country, COUNT(*) as c FROM scrapping_results WHERE location IS NOT NULL AND location!='' GROUP BY location ORDER BY c DESC LIMIT 8")->fetchAll(PDO::FETCH_ASSOC);
$_contacts=$_db->query("SELECT COUNT(*) FROM send_contacts WHERE status='active'")->fetchColumn();
?>
<!DOCTYPE html><html lang="fr"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1">
<title>WEVADS - Scraping Factory Enhanced</title>
<link href="https://fonts.googleapis.com/css2?family=DM+Sans:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;700&display=swap" rel="stylesheet">
<style>
:root{--bg:#060a14;--s:#0c1220;--s2:#111827;--b:#1e293b;--t:#e2e8f0;--d:#64748b;--cy:#22d3ee;--gn:#34d399;--am:#fbbf24;--rd:#f87171;--pu:#a78bfa;--bl:#60a5fa;--pk:#f472b6}
*{margin:0;padding:0;box-sizing:border-box}body{background:var(--bg);color:var(--t);font-family:'DM Sans',sans-serif;font-size:12px}
.mono{font-family:'JetBrains Mono',monospace}
.hdr{background:var(--s);border-bottom:1px solid var(--b);padding:14px 20px;display:flex;justify-content:space-between;align-items:center}
.hdr h1{font-size:18px;font-weight:700;margin-left:80px}.hdr h1 span{color:var(--gn)}
.wrap{padding:16px 20px;max-width:1500px;margin:0 auto}
.stats{display:grid;grid-template-columns:repeat(6,1fr);gap:10px;margin-bottom:16px}
.sc{background:var(--s);border:1px solid var(--b);border-radius:10px;padding:14px;text-align:center;cursor:pointer;transition:all .2s}
.sc:hover{transform:translateY(-2px);box-shadow:0 8px 24px rgba(0,0,0,.3);border-color:var(--gn)}
.sc .n{font-family:'JetBrains Mono',monospace;font-size:22px;font-weight:700}
.sc .l{font-size:9px;text-transform:uppercase;color:var(--d);margin-top:4px}
.sc .delta{font-size:9px;margin-top:3px}
.g2{display:grid;grid-template-columns:1fr 1fr;gap:12px}
.cd{background:var(--s);border:1px solid var(--b);border-radius:10px;padding:14px}
table{width:100%;border-collapse:collapse;font-size:11px}
th{text-align:left;color:var(--d);text-transform:uppercase;font-size:9px;padding:6px 8px;border-bottom:1px solid var(--b)}
td{padding:6px 8px;border-bottom:1px solid rgba(30,41,59,.3)}
.badge{font-size:8px;padding:2px 6px;border-radius:3px;font-weight:600}
.badge-gn{background:rgba(52,211,153,.15);color:var(--gn)}.badge-rd{background:rgba(248,113,113,.15);color:var(--rd)}.badge-am{background:rgba(251,191,36,.15);color:var(--am)}.badge-cy{background:rgba(34,211,238,.15);color:var(--cy)}.badge-pu{background:rgba(167,139,250,.15);color:var(--pu)}
.btn{padding:8px 16px;border-radius:6px;border:1px solid var(--b);background:var(--s2);color:var(--t);cursor:pointer;font-size:10px;font-weight:600;transition:all .2s;text-decoration:none}
.btn:hover{border-color:var(--gn);transform:translateY(-1px)}
.btn-gn{background:rgba(52,211,153,.12);border-color:var(--gn);color:var(--gn)}
.tabs{display:flex;gap:2px;margin-bottom:14px;border-bottom:1px solid var(--b)}
.tab{padding:8px 16px;cursor:pointer;font-size:10px;font-weight:600;text-transform:uppercase;color:var(--d);border-bottom:2px solid transparent}
.tab:hover{color:var(--t)}.tab.active{color:var(--gn);border-color:var(--gn)}
.panel{display:none}.panel.active{display:block}
.modal{display:none;position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,.75);z-index:9999;justify-content:center;align-items:center}
.modal-box{background:var(--s);border:1px solid var(--b);border-radius:12px;padding:20px;max-width:900px;width:92%;max-height:82vh;overflow-y:auto}
.pipeline{display:flex;align-items:center;gap:6px}.pipeline .stage{flex:1;background:var(--s2);border:1px solid var(--b);border-radius:8px;padding:10px;text-align:center}
.pipeline .arrow{color:var(--gn);font-size:18px}
.log{background:var(--s2);border:1px solid var(--b);border-radius:8px;padding:10px;font-family:'JetBrains Mono',monospace;font-size:10px;max-height:200px;overflow-y:auto}
.log div{padding:2px 0;border-bottom:1px solid rgba(30,41,59,.2)}
@media(max-width:900px){.stats{grid-template-columns:repeat(3,1fr)}.g2{grid-template-columns:1fr}}
</style>
<link rel="stylesheet" href="wevads-global.css?v1770777318">
</head><body>
<div class="hdr">
<div>
<h1><span>Scraping Factory Enhanced</span></h1>
<div style="color:var(--d);font-size:11px;margin-top:4px">Advanced scraping + enrichment + LinkedIn + ISP segmentation → Pipeline CRM</div>
</div>
<div style="display:flex;gap:8px;align-items:center">
<span class="badge badge-gn">● ENHANCED</span>
<a href="scrapping-factory.html" class="btn">Basic Factory</a>
<a href="menu.html" class="btn">Menu</a>
<a href="operations-overview.html" class="btn">← Overview</a>
</div>
</div>
<div class="wrap">
<div class="stats">
<div class="sc" onclick="drill('total')"><div class="n" style="color:var(--cy)"><?=number_format($_sf_total)?></div><div class="l">Total Scraped ▼</div><div class="delta" style="color:var(--gn)"><?=$_sf_targets?> active targets</div></div>
<div class="sc" onclick="drill('valid')"><div class="n" style="color:var(--gn)"><?=number_format($_sf_valid)?></div><div class="l">Verified ▼</div><div class="delta" style="color:var(--gn)"><?=$_sf_total>0?round($_sf_valid/$_sf_total*100,1):0?>%</div></div>
<div class="sc" onclick="drill('enriched')"><div class="n" style="color:var(--bl)"><?=number_format($_sf_enriched)?></div><div class="l">Enriched ▼</div><div class="delta" style="color:var(--cy)"><?=number_format($_sf_withCompany)?> companies</div></div>
<div class="sc" onclick="drill('linkedin')"><div class="n" style="color:var(--pu)"><?=number_format($_sf_linkedin)?></div><div class="l">LinkedIn ▼</div><div class="delta"><?=$_sf_jobs?> jobs total</div></div>
<div class="sc" onclick="drill('sources')"><div class="n" style="color:var(--am)"><?=number_format($_sf_withLoc)?></div><div class="l">Geo Located ▼</div><div class="delta"><?=$_sf_total>0?round($_sf_withLoc/$_sf_total*100,1):0?>% coverage</div></div>
<div class="sc" onclick="drill('pipeline')"><div class="n" style="color:var(--pk)"><?=number_format($_sf_inCRM)?></div><div class="l">→ CRM ▼</div><div class="delta" style="color:var(--gn)">pipeline flow</div></div>
</div>
<div class="tabs">
<div class="tab active" onclick="showTab('overview')">Overview</div>
<div class="tab" onclick="showTab('isp')">ISP Segmentation</div>
<div class="tab" onclick="showTab('geo')">Geo Distribution</div>
<div class="tab" onclick="showTab('actions')">Actions</div>
</div>
<div class="panel active" id="tab-overview">
<div class="g2">
<div class="cd">
<h3 style="font-size:13px;margin-bottom:10px;color:var(--gn)">📊 Enrichment Quality</h3>
<table><thead><tr><th>Metric</th><th>Value</th><th>Coverage</th></tr></thead><tbody>
<tr><td>Total Contacts</td><td class="mono"><?=number_format($_sf_total)?></td><td><span class="badge badge-cy">100%</span></td></tr>
<tr><td>Verified Emails</td><td class="mono"><?=number_format($_sf_valid)?></td><td><span class="badge badge-gn"><?=round($_sf_valid/max($_sf_total,1)*100)?>%</span></td></tr>
<tr><td>Full Names</td><td class="mono"><?=number_format($_sf_enriched)?></td><td><span class="badge <?=$_sf_enriched/$_sf_total>.4?'badge-am':'badge-rd'?>"><?=round($_sf_enriched/max($_sf_total,1)*100)?>%</span></td></tr>
<tr><td>Companies</td><td class="mono"><?=number_format($_sf_withCompany)?></td><td><span class="badge badge-pu"><?=round($_sf_withCompany/max($_sf_total,1)*100)?>%</span></td></tr>
<tr><td>Locations</td><td class="mono"><?=number_format($_sf_withLoc)?></td><td><span class="badge badge-gn"><?=round($_sf_withLoc/max($_sf_total,1)*100)?>%</span></td></tr>
<tr><td>LinkedIn Sources</td><td class="mono"><?=number_format($_sf_linkedin)?></td><td><span class="badge badge-pu"><?=round($_sf_linkedin/max($_sf_total,1)*100)?>%</span></td></tr>
<tr><td>Synced to CRM</td><td class="mono"><?=number_format($_sf_inCRM)?></td><td><span class="badge <?=$_sf_inCRM>0?'badge-gn':'badge-rd'?>"><?=$_sf_inCRM>0?'SYNCED':'PENDING'?></span></td></tr>
</tbody></table>
</div>
<div class="cd">
<h3 style="font-size:13px;margin-bottom:10px;color:var(--am)">📦 Pipeline Status</h3>
<div class="pipeline" style="margin-bottom:14px">
<div class="stage"><div style="font-size:16px;font-weight:700;color:var(--cy)"><?=number_format($_sf_total)?></div><div style="font-size:8px;color:var(--d)">Scraped</div></div>
<div class="arrow"></div>
<div class="stage"><div style="font-size:16px;font-weight:700;color:var(--gn)"><?=number_format($_sf_valid)?></div><div style="font-size:8px;color:var(--d)">Verified</div></div>
<div class="arrow"></div>
<div class="stage"><div style="font-size:16px;font-weight:700;color:var(--bl)"><?=number_format($_sf_enriched)?></div><div style="font-size:8px;color:var(--d)">Enriched</div></div>
<div class="arrow"></div>
<div class="stage"><div style="font-size:16px;font-weight:700;color:var(--pk)"><?=number_format($_sf_inCRM)?></div><div style="font-size:8px;color:var(--d)">CRM</div></div>
<div class="arrow"></div>
<div class="stage"><div style="font-size:16px;font-weight:700;color:var(--gn)"><?=number_format($_contacts)?></div><div style="font-size:8px;color:var(--d)">Send</div></div>
</div>
<div id="logbox" class="log"><div style="color:var(--gn)">✓ System ready</div></div>
</div>
</div>
</div>
<div class="panel" id="tab-isp">
<div class="cd">
<h3 style="font-size:13px;margin-bottom:10px;color:var(--cy)">📧 ISP Segmentation</h3>
<table><thead><tr><th>ISP/Provider</th><th>Count</th><th>%</th></tr></thead><tbody>
<?php foreach($_isps as $i): $pct=$_sf_total>0?round($i['c']/$_sf_total*100,1):0; ?>
<tr><td style="font-weight:600"><?=htmlspecialchars($i['isp'])?></td><td class="mono"><?=number_format($i['c'])?></td><td><?=$pct?>%</td></tr>
<?php endforeach; ?>
</tbody></table>
</div>
</div>
<div class="panel" id="tab-geo">
<div class="cd">
<h3 style="font-size:13px;margin-bottom:10px;color:var(--am)">🌍 Geographic Distribution</h3>
<table><thead><tr><th>Country</th><th>Count</th><th>%</th></tr></thead><tbody>
<?php foreach($_countries as $c): $pct=$_sf_total>0?round($c['c']/$_sf_total*100,1):0; ?>
<tr><td style="font-weight:600"><?=htmlspecialchars($c['country'])?></td><td class="mono"><?=number_format($c['c'])?></td><td><?=$pct?>%</td></tr>
<?php endforeach; ?>
</tbody></table>
</div>
</div>
<div class="panel" id="tab-actions">
<div class="g2">
<div class="cd">
<h3 style="font-size:13px;margin-bottom:10px;color:var(--gn)">🔄 Sync Pipeline</h3>
<p style="color:var(--d);margin-bottom:12px">Push all verified+enriched contacts to CRM and Send pipeline.</p>
<button class="btn btn-gn" style="width:100%;padding:12px" onclick="syncPipeline()">🔄 Sync to CRM + Send</button>
<div id="syncResult" style="margin-top:10px"></div>
</div>
<div class="cd">
<h3 style="font-size:13px;margin-bottom:10px;color:var(--cy)">📥 Export Data</h3>
<p style="color:var(--d);margin-bottom:12px">Download all enriched contacts as CSV.</p>
<a href="/api/advanced-scraping.php?action=export&format=csv" class="btn" style="display:block;text-align:center;padding:12px;background:rgba(34,211,238,.12);border-color:var(--cy);color:var(--cy)">📥 Download CSV</a>
</div>
</div>
</div>
</div>
<div class="modal" id="drillModal" onclick="if(event.target===this)this.style.display='none'">
<div class="modal-box">
<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:14px">
<h3 id="drillTitle" style="font-size:14px;color:var(--gn)"></h3>
<button onclick="document.getElementById('drillModal').style.display='none'" style="background:none;border:none;color:var(--rd);font-size:18px;cursor:pointer"></button>
</div>
<div id="drillContent" style="font-size:11px"></div>
</div>
</div>
<script>
function showTab(id){document.querySelectorAll('.tab').forEach(function(t){t.classList.remove('active')});document.querySelectorAll('.panel').forEach(function(p){p.classList.remove('active')});document.getElementById('tab-'+id).classList.add('active');event.target.classList.add('active')}
async function drill(type){
var m=document.getElementById('drillModal'),tt=document.getElementById('drillTitle'),ct=document.getElementById('drillContent');
m.style.display='flex';ct.innerHTML='<div style="text-align:center;padding:40px;color:var(--d)">Loading...</div>';
try{
var html='';
if(type==='total'||type==='valid'||type==='enriched'||type==='linkedin'){
var titles={total:'📊 All Contacts',valid:'✅ Verified',enriched:'👤 Enriched',linkedin:'💼 LinkedIn Sourced'};
tt.textContent=titles[type]||type;
var pg=arguments[1]||1;
var r=await fetch('/api/advanced-scraping.php?action=drill_total&page='+pg);
var d=(await r.json()).data||{};
html+='<div style="display:grid;grid-template-columns:repeat(3,1fr);gap:8px;margin-bottom:12px">';
html+='<div class="cd" style="text-align:center"><div class="n" style="color:var(--gn);font-size:20px">'+(d.verified||0).toLocaleString()+'</div><div class="l">Verified</div></div>';
html+='<div class="cd" style="text-align:center"><div class="n" style="color:var(--rd);font-size:20px">'+(d.unverified||0).toLocaleString()+'</div><div class="l">Unverified</div></div>';
html+='<div class="cd" style="text-align:center"><div class="n" style="color:var(--cy);font-size:20px">'+(d.total_contacts||0).toLocaleString()+'</div><div class="l">Total</div></div>';
html+='</div>';
html+='<div style="overflow-x:auto"><table><thead><tr><th>Email</th><th>Name</th><th>Company</th><th>Location</th><th>Source</th><th>✓</th></tr></thead><tbody>';
(d.contacts||[]).forEach(function(c){html+='<tr><td style="color:var(--cy);font-family:monospace;font-size:11px">'+(c.email||'-')+'</td><td>'+(c.full_name||'—')+'</td><td>'+(c.company||'—')+'</td><td>'+(c.location||'—')+'</td><td style="font-size:10px">'+(c.source||'-').substring(0,30)+'</td><td>'+(c.is_verified?'✅':'❌')+'</td></tr>';});
html+='</tbody></table></div>';
if((d.pages||1)>1){html+='<div style="display:flex;gap:8px;justify-content:center;margin-top:10px">';if(d.page>1)html+='<button class="btn" onclick="drill(\''+type+'\','+(d.page-1)+')">◄</button>';html+='<span style="color:var(--d);line-height:32px">'+d.page+'/'+d.pages+'</span>';if(d.page<d.pages)html+='<button class="btn" onclick="drill(\''+type+'\','+(d.page+1)+')">►</button>';html+='</div>';}
} else if(type==='sources'){
tt.textContent='🌍 Geo & Quality';
var r=await fetch('/api/pipeline-sync.php?action=drill&type=scraping_quality');var d=await r.json();
html+='<div style="display:grid;grid-template-columns:repeat(3,1fr);gap:8px;margin-bottom:12px">';
(d.summary||[]).forEach(function(s){html+='<div class="cd" style="text-align:center"><div style="font-size:18px;font-weight:700;color:'+(s.color||'var(--cy)')+'">'+Number(s.value).toLocaleString()+'</div><div class="l">'+s.label+'</div></div>';});
html+='</div>';
if(d.by_country){html+='<table><thead><tr><th>Country</th><th>Count</th></tr></thead><tbody>';d.by_country.forEach(function(c){html+='<tr><td>'+c.country+'</td><td>'+Number(c.cnt).toLocaleString()+'</td></tr>';});html+='</tbody></table>';}
} else if(type==='pipeline'){
tt.textContent='🔄 Pipeline Flow';
var r=await fetch('/api/pipeline-sync.php?action=drill&type=pipeline');var stages=(await r.json()).stages||[];
html+='<div class="pipeline" style="margin-bottom:14px">';
stages.forEach(function(s,i){html+='<div class="stage"><div style="font-size:20px;font-weight:700;color:'+s.color+'">'+Number(s.count).toLocaleString()+'</div><div style="font-size:9px;color:var(--d)">'+s.name+'</div></div>';if(i<stages.length-1)html+='<div class="arrow">→</div>';});
html+='</div>';
var r2=await fetch('/api/pipeline-sync.php?action=status');var p=(await r2.json()).pipeline||{};
html+='<div class="cd"><div class="g2"><div>Not in CRM: <strong style="color:'+(p.scrapping_not_in_crm>0?'var(--rd)':'var(--gn)')+'">'+p.scrapping_not_in_crm+'</strong></div><div>Not in Send: <strong style="color:'+(p.scrapping_not_in_send>0?'var(--rd)':'var(--gn)')+'">'+p.scrapping_not_in_send+'</strong></div></div></div>';
html+='<div style="text-align:center;margin-top:14px"><button class="btn btn-gn" style="padding:12px 40px" onclick="syncPipeline()">🔄 Sync All</button></div>';
}
ct.innerHTML=html;
}catch(e){ct.innerHTML='<div style="color:var(--rd)">Error: '+e.message+'</div>';}
}
async function syncPipeline(){var el=document.getElementById('syncResult')||document.getElementById('drillContent');el.innerHTML='<div style="text-align:center;padding:20px;color:var(--am)">⏳ Syncing...</div>';try{var r=await fetch('/api/pipeline-sync.php?action=sync');var d=await r.json();var s=d.synced||{};el.innerHTML='<div style="text-align:center;padding:15px"><div style="font-size:30px">✅</div><div style="color:var(--gn);font-weight:700">Done</div><div style="margin-top:8px;color:var(--d)">CRM: '+s.scraping_to_crm+' | Send: '+s.scraping_to_send+' | Harvest: '+s.harvest_to_crm+'</div></div>';}catch(e){el.innerHTML='<div style="color:var(--rd)">'+e.message+'</div>';}}
</script>
<script src="arsenal-common.js?v1770778169"></script>
<?php include("/opt/wevads-arsenal/public/universal-drill.html"); ?>
</body></html>