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

180 lines
17 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");
$_hp=(int)$_db->query("SELECT COUNT(*) FROM personas")->fetchColumn();
$_ps=(int)$_db->query("SELECT COUNT(*) FROM personas")->fetchColumn();
$_bc=(int)$_db->query("SELECT COUNT(*) FROM brain_send_configs")->fetchColumn();
$_bw=(int)$_db->query("SELECT COUNT(*) FROM brain_send_configs WHERE is_winner=true")->fetchColumn();
$_sc=(int)$_db->query("SELECT COUNT(*) FROM scrapping_results")->fetchColumn();
$_sv=(int)$_db->query("SELECT COUNT(*) FROM scrapping_results WHERE is_verified=true")->fetchColumn();
$_send=(int)$_db->query("SELECT COUNT(*) FROM send_contacts WHERE status='active'")->fetchColumn();
$_cr=(int)$_db->query("SELECT COUNT(*) FROM offer_creatives")->fetchColumn();
// Top personas
$_personas=$_db->query("SELECT id, first_name||' '||last_name as name, COALESCE(country,'?') as style, CASE WHEN is_active THEN 1 ELSE 0 END as score FROM personas ORDER BY id DESC LIMIT 10")->fetchAll(PDO::FETCH_ASSOC);
if(empty($_personas)) $_personas=[];
// Brain configs
$_configs=$_db->query("SELECT id, send_method||' → '||isp_target as name, is_winner, COALESCE(inbox_rate,0) as inbox_rate, COALESCE(total_sent,0) as total_sent FROM brain_send_configs ORDER BY is_winner DESC, inbox_rate DESC LIMIT 10")->fetchAll(PDO::FETCH_ASSOC);
?>
<!DOCTYPE html><html lang="fr"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1">
<title>WEVADS - Lookalike Engine</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(--pu)}
.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(--pu)}
.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(--pu);transform:translateY(-1px)}
.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(--pu);border-color:var(--pu)}
.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(--pu);font-size:18px}
@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>Lookalike Engine</span></h1>
<div style="color:var(--d);font-size:11px;margin-top:4px">Persona generation — brain config optimization — audience modeling</div>
</div>
<div style="display:flex;gap:8px;align-items:center">
<span class="badge badge-pu">● ENGINE</span>
<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('personas')"><div class="n" style="color:var(--pu)"><?=$_hp?></div><div class="l">HAMID Personas ▼</div><div class="delta">AI-generated</div></div>
<div class="sc" onclick="drill('fingerprints')"><div class="n" style="color:var(--cy)"><?=$_ps?></div><div class="l">Fingerprints ▼</div><div class="delta">unique profiles</div></div>
<div class="sc" onclick="drill('configs')"><div class="n" style="color:var(--am)"><?=$_bc?></div><div class="l">Brain Configs ▼</div><div class="delta"><?=$_bw?> winners</div></div>
<div class="sc" onclick="drill('creatives')"><div class="n" style="color:var(--gn)"><?=$_cr?></div><div class="l">Creatives ▼</div><div class="delta">active templates</div></div>
<div class="sc" onclick="drill('scraped')"><div class="n" style="color:var(--bl)"><?=number_format($_sc)?></div><div class="l">Scraped ▼</div><div class="delta"><?=number_format($_sv)?> verified</div></div>
<div class="sc" onclick="drill('pipeline')"><div class="n" style="color:var(--pk)"><?=number_format($_send)?></div><div class="l">Send Pool ▼</div><div class="delta" style="color:var(--gn)">pipeline</div></div>
</div>
<div class="tabs">
<div class="tab active" onclick="showTab('personas')">Personas</div>
<div class="tab" onclick="showTab('configs')">Brain Configs</div>
<div class="tab" onclick="showTab('model')">Audience Model</div>
</div>
<div class="panel active" id="tab-personas">
<div class="cd">
<h3 style="font-size:13px;margin-bottom:10px;color:var(--pu)">🧬 HAMID Personas</h3>
<table><thead><tr><th>ID</th><th>Name</th><th>Style</th><th>Score</th></tr></thead><tbody>
<?php foreach($_personas as $p): ?>
<tr><td>#<?=$p['id']?></td><td style="font-weight:600"><?=htmlspecialchars($p['name'])?></td><td><span class="badge badge-pu"><?=htmlspecialchars($p['style'])?></span></td><td class="mono"><?=$p['score']?></td></tr>
<?php endforeach;if(empty($_personas)):?><tr><td colspan="4" style="text-align:center;color:var(--d);padding:20px">No personas</td></tr><?php endif;?>
</tbody></table>
</div>
</div>
<div class="panel" id="tab-configs">
<div class="cd">
<h3 style="font-size:13px;margin-bottom:10px;color:var(--am)">🧠 Brain Configs</h3>
<table><thead><tr><th>ID</th><th>Name</th><th>Winner</th><th>Inbox Rate</th><th>Total Sent</th></tr></thead><tbody>
<?php foreach($_configs as $cfg): ?>
<tr><td>#<?=$cfg['id']?></td><td style="font-weight:600"><?=htmlspecialchars($cfg['name'])?></td><td><?=$cfg['is_winner']?'<span class="badge badge-gn">⭐ WINNER</span>':'<span class="badge badge-am">TEST</span>'?></td><td class="mono" style="color:<?=$cfg['inbox_rate']>80?'var(--gn)':($cfg['inbox_rate']>50?'var(--am)':'var(--rd)')?>"><?=$cfg['inbox_rate']?>%</td><td class="mono"><?=number_format($cfg['total_sent'])?></td></tr>
<?php endforeach;if(empty($_configs)):?><tr><td colspan="5" style="text-align:center;color:var(--d);padding:20px">No configs</td></tr><?php endif;?>
</tbody></table>
</div>
</div>
<div class="panel" id="tab-model">
<div class="g2">
<div class="cd">
<h3 style="font-size:13px;margin-bottom:10px;color:var(--gn)">📊 Audience Model</h3>
<table><thead><tr><th>Metric</th><th>Value</th></tr></thead><tbody>
<tr><td>HAMID Personas</td><td class="mono"><?=$_hp?></td></tr>
<tr><td>Fingerprints</td><td class="mono"><?=$_ps?></td></tr>
<tr><td>Brain Configs</td><td class="mono"><?=$_bc?> (<?=$_bw?> winners)</td></tr>
<tr><td>Creatives</td><td class="mono"><?=$_cr?></td></tr>
<tr><td>Scraped Contacts</td><td class="mono"><?=number_format($_sc)?></td></tr>
<tr><td>Send Pool</td><td class="mono"><?=number_format($_send)?></td></tr>
</tbody></table>
</div>
<div class="cd">
<h3 style="font-size:13px;margin-bottom:10px;color:var(--pu)">🔄 Pipeline</h3>
<div class="pipeline" style="margin-bottom:12px">
<div class="stage"><div style="font-size:14px;font-weight:700;color:var(--pu)"><?=$_hp?></div><div style="font-size:8px;color:var(--d)">Personas</div></div>
<div class="arrow"></div>
<div class="stage"><div style="font-size:14px;font-weight:700;color:var(--am)"><?=$_bc?></div><div style="font-size:8px;color:var(--d)">Configs</div></div>
<div class="arrow"></div>
<div class="stage"><div style="font-size:14px;font-weight:700;color:var(--gn)"><?=$_cr?></div><div style="font-size:8px;color:var(--d)">Creatives</div></div>
<div class="arrow"></div>
<div class="stage"><div style="font-size:14px;font-weight:700;color:var(--pk)"><?=number_format($_send)?></div><div style="font-size:8px;color:var(--d)">Send</div></div>
</div>
<button class="btn" style="width:100%;padding:12px;background:rgba(52,211,153,.12);border-color:var(--gn);color:var(--gn)" onclick="syncPipeline()">🔄 Sync Pipeline</button>
<div id="syncResult" style="margin-top:10px"></div>
</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(--pu)"></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==='personas'){
tt.textContent='🧬 HAMID Personas Detail';
html+='<div class="cd" style="text-align:center;margin-bottom:12px"><div style="font-size:28px;font-weight:700;color:var(--pu)"><?=$_hp?></div><div class="l">AI-Generated Personas</div></div>';
html+='<div class="cd" style="color:var(--d)">HAMID personas are AI-generated behavioral profiles used to model audience segments. Each persona defines email style, timing patterns, and engagement characteristics for optimized delivery.</div>';
} else if(type==='fingerprints'){
tt.textContent='🔐 Fingerprints';
html+='<div class="g2" style="margin-bottom:12px"><div class="cd" style="text-align:center"><div style="font-size:28px;font-weight:700;color:var(--cy)"><?=$_ps?></div><div class="l">Unique Profiles</div></div><div class="cd" style="text-align:center"><div style="font-size:28px;font-weight:700;color:var(--pu)"><?=$_hp?></div><div class="l">Persona Models</div></div></div>';
} else if(type==='configs'){
tt.textContent='🧠 Brain Configs Analysis';
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 style="font-size:22px;font-weight:700;color:var(--am)"><?=$_bc?></div><div class="l">Total Configs</div></div>';
html+='<div class="cd" style="text-align:center"><div style="font-size:22px;font-weight:700;color:var(--gn)"><?=$_bw?></div><div class="l">Winners</div></div>';
html+='<div class="cd" style="text-align:center"><div style="font-size:22px;font-weight:700;color:var(--pu)"><?=round($_bw/max($_bc,1)*100)?>%</div><div class="l">Win Rate</div></div>';
html+='</div>';
} else if(type==='creatives'){
tt.textContent='🎨 Active Creatives';
html+='<div class="cd" style="text-align:center"><div style="font-size:28px;font-weight:700;color:var(--gn)"><?=$_cr?></div><div class="l">Active Templates</div></div>';
} else if(type==='scraped'){
tt.textContent='📊 Scraped Contacts';
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 style="font-size:20px;font-weight:700;color:var(--gn)">'+(d.verified||0).toLocaleString()+'</div><div class="l">Verified</div></div>';
html+='<div class="cd" style="text-align:center"><div style="font-size:20px;font-weight:700;color:var(--rd)">'+(d.unverified||0).toLocaleString()+'</div><div class="l">Unverified</div></div>';
html+='<div class="cd" style="text-align:center"><div style="font-size:20px;font-weight:700;color:var(--cy)">'+(d.total_contacts||0).toLocaleString()+'</div><div class="l">Total</div></div>';
html+='</div><div style="overflow-x:auto"><table><thead><tr><th>Email</th><th>Name</th><th>Company</th><th>Location</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>'+(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(\'scraped\','+(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(\'scraped\','+(d.page+1)+')">►</button>';html+='</div>';}
} else if(type==='pipeline'){
tt.textContent='🔄 Full Pipeline';
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>';
html+='<div style="text-align:center"><button class="btn" style="padding:12px 40px;background:rgba(52,211,153,.12);border-color:var(--gn);color:var(--gn)" onclick="syncPipeline()">🔄 Sync All</button></div>';
}
ct.innerHTML=html;
}catch(e){ct.innerHTML='<div style="color:var(--rd)">'+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)">⏳</div>';try{var r=await fetch('/api/pipeline-sync.php?action=sync');var s=(await r.json()).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="color:var(--d);margin-top:8px">CRM: '+s.scraping_to_crm+' | Send: '+s.scraping_to_send+'</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>