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

300 lines
17 KiB
HTML
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php include_once("/opt/wevads-arsenal/public/api/wevads-metrics.php"); ?>
<!DOCTYPE html>
<html lang="en" data-theme="dark">
<head>
<meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1">
<title>WEVADS — Global Vision</title>
<link href="https://fonts.googleapis.com/css2?family=Space+Mono:wght@400;700&family=DM+Sans:wght@400;500;600;700&display=swap" rel="stylesheet">
<style>
:root{--bg:#06090f;--s:#0d1117;--s2:#161b22;--b:#21262d;--t:#e6edf3;--d:#7d8590;--cy:#58a6ff;--gn:#3fb950;--am:#d29922;--rd:#f85149;--pu:#bc8cff;--pk:#f778ba;--or:#ff7b72}
*{box-sizing:border-box;margin:0;padding:0}
body{font-family:'DM Sans',sans-serif;background:var(--bg);color:var(--t);overflow-x:hidden}
.top{background:linear-gradient(135deg,#0d1117 0%,#161b22 100%);border-bottom:1px solid var(--b);padding:16px 24px;display:flex;align-items:center;justify-content:space-between}
.top h1{font-family:'Space Mono',monospace;font-size:18px;color:var(--cy)}
.top h1 span{color:var(--d);font-weight:400}
.top-links{display:flex;gap:8px}
.top-links a{padding:6px 14px;background:var(--s2);border:1px solid var(--b);border-radius:6px;color:var(--d);text-decoration:none;font-size:12px;font-weight:500;transition:.2s}
.top-links a:hover{color:var(--cy);border-color:var(--cy)}
.grid{display:grid;grid-template-columns:1fr 1fr 1fr 1fr;gap:12px;padding:16px 24px}
@media(max-width:1200px){.grid{grid-template-columns:1fr 1fr}}
.card{background:var(--s);border:1px solid var(--b);border-radius:10px;padding:16px;position:relative;overflow:hidden}
.card::before{content:'';position:absolute;top:0;left:0;right:0;height:2px}
.card.cy::before{background:var(--cy)}.card.gn::before{background:var(--gn)}.card.am::before{background:var(--am)}.card.rd::before{background:var(--rd)}.card.pu::before{background:var(--pu)}.card.pk::before{background:var(--pk)}.card.or::before{background:var(--or)}
.card-title{font-family:'Space Mono',monospace;font-size:11px;text-transform:uppercase;letter-spacing:1.5px;color:var(--d);margin-bottom:12px;display:flex;align-items:center;gap:8px}
.card-title .ico{font-size:14px}
.big{font-size:28px;font-weight:700;font-family:'Space Mono',monospace;margin-bottom:4px}
.big.cy{color:var(--cy)}.big.gn{color:var(--gn)}.big.am{color:var(--am)}.big.rd{color:var(--rd)}.big.pu{color:var(--pu)}
.sub{font-size:12px;color:var(--d)}
.row{display:flex;gap:16px;flex-wrap:wrap;margin-top:10px}
.mini{flex:1;min-width:80px;background:var(--s2);border-radius:6px;padding:8px 10px;text-align:center}
.mini-val{font-size:16px;font-weight:700;font-family:'Space Mono',monospace}
.mini-lbl{font-size:10px;color:var(--d);margin-top:2px}
.isp-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(100px,1fr));gap:6px;margin-top:10px}
.isp-chip{background:var(--s2);border:1px solid var(--b);border-radius:6px;padding:6px 8px;text-align:center;font-size:11px}
.isp-chip .name{font-weight:600;color:var(--t);text-transform:uppercase;font-size:10px}
.isp-chip .cnt{font-family:'Space Mono',monospace;color:var(--cy);font-size:13px;font-weight:700}
.isp-chip.seed{border-color:#d29922;background:rgba(210,153,34,.08)}
.isp-chip.seed .cnt{color:var(--am)}
.flow{grid-column:1/-1;display:flex;align-items:center;justify-content:center;gap:4px;padding:12px;flex-wrap:wrap}
.flow-step{background:var(--s2);border:1px solid var(--b);border-radius:8px;padding:10px 14px;text-align:center;min-width:100px;transition:.2s}
.flow-step:hover{border-color:var(--cy);transform:translateY(-2px)}
.flow-step .f-ico{font-size:20px;margin-bottom:4px}
.flow-step .f-name{font-size:10px;font-weight:600;text-transform:uppercase;letter-spacing:.5px}
.flow-step .f-val{font-family:'Space Mono',monospace;font-size:14px;font-weight:700;color:var(--cy)}
.flow-arrow{color:var(--d);font-size:18px;font-family:'Space Mono',monospace}
.bar{height:6px;background:var(--s2);border-radius:3px;margin-top:6px;overflow:hidden}
.bar-fill{height:100%;border-radius:3px;transition:width .8s ease}
.bar-fill.cy{background:var(--cy)}.bar-fill.gn{background:var(--gn)}.bar-fill.am{background:var(--am)}.bar-fill.rd{background:var(--rd)}.bar-fill.pu{background:var(--pu)}
.link-row{display:flex;gap:6px;margin-top:8px;flex-wrap:wrap}
.link-btn{padding:4px 10px;background:var(--s2);border:1px solid var(--b);border-radius:4px;color:var(--cy);text-decoration:none;font-size:10px;font-weight:600;transition:.2s}
.link-btn:hover{background:var(--cy);color:var(--bg)}
.status-dot{width:8px;height:8px;border-radius:50%;display:inline-block}
.status-dot.on{background:var(--gn);box-shadow:0 0 6px var(--gn)}.status-dot.off{background:var(--rd)}
.wide{grid-column:span 2}
.full{grid-column:1/-1}
#loading{position:fixed;top:0;left:0;right:0;bottom:0;background:var(--bg);display:flex;align-items:center;justify-content:center;z-index:999;font-family:'Space Mono',monospace;color:var(--cy)}
@keyframes pulse{0%,100%{opacity:.4}50%{opacity:1}}
#loading span{animation:pulse 1s infinite}
</style>
</head>
<body>
<div id="loading"><span>LOADING GLOBAL VISION...</span></div>
<div class="top">
<h1>⚡ WEVADS GLOBAL VISION <span>/ pipeline × crm × data</span></h1>
<div class="top-links">
<a href="crm.php">📇 CRM</a>
<a href="data-manager.html">💾 Data Manager</a>
<a href="emailing-pipeline.html">🔗 Pipeline</a>
<a href="brain-central.html">🧠 Brain</a>
<a href="ceo-dashboard.html">👔 CEO</a>
<a href="menu.html">☰ Menu</a>
</div>
</div>
<div class="grid" id="dash"></div>
<script>
const API = '/api/crm-api.php';
const fmt = n => {
if(n===null||n===undefined) return '0';
n = parseInt(n)||0;
if(n>=1e6) return (n/1e6).toFixed(1)+'M';
if(n>=1e3) return (n/1e3).toFixed(1)+'K';
return n.toLocaleString();
};
async function load() {
try {
const [vision, pipeline] = await Promise.all([
fetch(API+'?action=global_vision').then(r=>r.json()),
fetch(API+'?action=pipeline_status').then(r=>r.json())
]);
const v = vision.vision;
const p = pipeline.pipeline;
render(v, p);
} catch(e) {
document.getElementById('dash').innerHTML = `<div class="card full rd"><div class="card-title">ERROR</div><div class="sub">${e.message}</div></div>`;
}
document.getElementById('loading').style.display='none';
}
function render(v, p) {
const dash = document.getElementById('dash');
// E2E FLOW
const flowSteps = [
{ico:'🏭',name:'Supply',val:fmt(v.infra.o365_tenants)+' O365'},
{ico:'🏗️',name:'Infra',val:fmt(v.capacity.warming)+' warm'},
{ico:'🧠',name:'Brain',val:v.capacity.send_methods+' methods'},
{ico:'👥',name:'CRM',val:fmt(v.data.crm_leads)+' leads'},
{ico:'🎯',name:'Offers',val:v.offers.active+' active'},
{ico:'📤',name:'Send',val:fmt(v.capacity.daily_cap)+'/day'},
{ico:'📊',name:'Track',val:fmt(v.tracking.clicks)+' clicks'},
{ico:'💰',name:'Revenue',val:'$'+v.tracking.revenue.toFixed(0)},
];
let flowHTML = '<div class="card full" style="border-color:var(--cy)"><div class="card-title"><span class="ico">🔗</span>E2E PIPELINE FLOW</div><div class="flow">';
flowSteps.forEach((s,i) => {
flowHTML += `<div class="flow-step"><div class="f-ico">${s.ico}</div><div class="f-name">${s.name}</div><div class="f-val">${s.val}</div></div>`;
if(i < flowSteps.length-1) flowHTML += '<span class="flow-arrow">→</span>';
});
flowHTML += '</div></div>';
// DATA POOLS
const dataPools = `
<div class="card wide cy">
<div class="card-title"><span class="ico">💾</span>DATA POOLS</div>
<div class="big cy">${fmt(v.data.crm_leads + v.data.send_data + v.data.encrypted)}</div>
<div class="sub">Total addressable contacts</div>
<div class="row">
<div class="mini"><div class="mini-val" style="color:var(--cy)">${fmt(v.data.crm_leads)}</div><div class="mini-lbl">CRM Leads</div></div>
<div class="mini"><div class="mini-val" style="color:var(--gn)">${fmt(v.data.send_data)}</div><div class="mini-lbl">Send Data</div></div>
<div class="mini"><div class="mini-val" style="color:var(--pu)">${fmt(v.data.encrypted)}</div><div class="mini-lbl">Encrypted</div></div>
<div class="mini"><div class="mini-val" style="color:var(--am)">${v.data.adx_bridge}</div><div class="mini-lbl">ADX Bridge</div></div>
<div class="mini"><div class="mini-val" style="color:var(--pk)">${fmt(v.data.seeds)}</div><div class="mini-lbl">Seeds</div></div>
<div class="mini"><div class="mini-val" style="color:var(--rd)">${fmt(v.data.suppressed)}</div><div class="mini-lbl">Suppressed</div></div>
</div>
<div class="link-row">
<a href="crm.php" class="link-btn">📇 CRM</a>
<a href="data-manager.html" class="link-btn">💾 Data Mgr</a>
<a href="send-data-factory.html" class="link-btn">📦 Send Data</a>
<a href="seed-cleaner.html" class="link-btn">🧹 Seeds</a>
<a href="harvest-manager.html" class="link-btn">🌾 Harvest</a>
</div>
</div>`;
// ISP COVERAGE
const totalLeads = v.isps.reduce((s,i)=>s+parseInt(i.cnt),0);
let ispHTML = '<div class="card wide am"><div class="card-title"><span class="ico">📧</span>ISP COVERAGE — ' + v.isps.length + ' ISPs</div>';
ispHTML += '<div class="isp-grid">';
v.isps.forEach(isp => {
const pct = (parseInt(isp.cnt)/totalLeads*100).toFixed(1);
const cls = parseInt(isp.cnt) <= 5 ? ' seed' : '';
ispHTML += `<div class="isp-chip${cls}"><div class="name">${isp.isp}</div><div class="cnt">${fmt(isp.cnt)}</div><div style="font-size:9px;color:var(--d)">${pct}%</div></div>`;
});
ispHTML += '</div><div class="sub" style="margin-top:8px">🟡 Seeds needed: ' + v.isps.filter(i=>parseInt(i.cnt)<=5).map(i=>i.isp).join(', ') + '</div></div>';
// CAPACITY
const capacity = `
<div class="card gn">
<div class="card-title"><span class="ico">⚡</span>SEND CAPACITY</div>
<div class="big gn">${fmt(v.capacity.daily_cap)}</div>
<div class="sub">emails/day capacity</div>
<div class="row">
<div class="mini"><div class="mini-val">${fmt(v.capacity.accounts)}</div><div class="mini-lbl">Accounts</div></div>
<div class="mini"><div class="mini-val">${v.capacity.warming}</div><div class="mini-lbl">Warming</div></div>
<div class="mini"><div class="mini-val">${v.capacity.send_methods}</div><div class="mini-lbl">Methods</div></div>
</div>
<div class="link-row">
<a href="warming-engine.html" class="link-btn">🔥 Warmup</a>
<a href="send-engines-dashboard.html" class="link-btn">🚀 Engines</a>
<a href="operations-overview.html" class="link-btn">🖥️ MTA</a>
</div>
</div>`;
// BRAIN
const brain = `
<div class="card pu">
<div class="card-title"><span class="ico">🧠</span>BRAIN ENGINE</div>
<div class="big pu">${v.brain.configs}</div>
<div class="sub">${v.brain.winners} winners / ${v.brain.tests} tests</div>
<div class="row">
<div class="mini"><div class="mini-val">${fmt(v.brain.creatives)}</div><div class="mini-lbl">Creatives</div></div>
<div class="mini"><div class="mini-val">${v.capacity.send_methods}</div><div class="mini-lbl">Methods</div></div>
</div>
<div class="link-row">
<a href="brain-central.html" class="link-btn">🧠 Central</a>
<a href="brain-combo-discovery.html" class="link-btn">🔬 Combos</a>
<a href="winning-config.html" class="link-btn">🏆 Winners</a>
</div>
</div>`;
// OFFERS
const offers = `
<div class="card or">
<div class="card-title"><span class="ico">🎯</span>OFFERS</div>
<div class="big" style="color:var(--or)">${v.offers.active}</div>
<div class="sub">${v.offers.total} total / ${v.offers.countries} countries</div>
<div class="link-row">
<a href="offer-engine.html" class="link-btn">🎯 Offers</a>
<a href="affiliate-monitor.html" class="link-btn">📡 CX3</a>
<a href="ai-copywriter.html" class="link-btn">✍️ Copy</a>
</div>
</div>`;
// TRACKING
const sent = v.tracking.sent;
const openRate = sent > 0 ? ((v.tracking.opens/sent)*100).toFixed(1) : '0';
const clickRate = sent > 0 ? ((v.tracking.clicks/sent)*100).toFixed(1) : '0';
const convRate = v.tracking.clicks > 0 ? ((v.tracking.conversions/v.tracking.clicks)*100).toFixed(1) : '0';
const tracking = `
<div class="card pk">
<div class="card-title"><span class="ico">📊</span>TRACKING & FUNNEL</div>
<div class="row">
<div class="mini"><div class="mini-val">${fmt(sent)}</div><div class="mini-lbl">Sent</div></div>
<div class="mini"><div class="mini-val">${fmt(v.tracking.opens)}</div><div class="mini-lbl">Opens ${openRate}%</div></div>
<div class="mini"><div class="mini-val">${fmt(v.tracking.clicks)}</div><div class="mini-lbl">Clicks ${clickRate}%</div></div>
<div class="mini"><div class="mini-val">${v.tracking.conversions}</div><div class="mini-lbl">Conv ${convRate}%</div></div>
<div class="mini"><div class="mini-val">${v.tracking.bounces}</div><div class="mini-lbl">Bounces</div></div>
</div>
<div class="bar"><div class="bar-fill pk" style="width:${Math.min(100,sent>0?v.tracking.opens/sent*100:5)}%"></div></div>
<div class="link-row">
<a href="tracking-arsenal.html" class="link-btn">📊 Tracking</a>
<a href="world-map-live.html" class="link-btn">🗺️ Map</a>
<a href="test-results-live.html" class="link-btn">📈 Live</a>
</div>
</div>`;
// REVENUE
const revenue = `
<div class="card gn">
<div class="card-title"><span class="ico">💰</span>REVENUE</div>
<div class="big gn">$${v.tracking.revenue.toFixed(2)}</div>
<div class="sub">${v.tracking.conversions} conversions</div>
<div class="link-row">
<a href="profit-orchestrator.html" class="link-btn">💎 Profit</a>
<a href="financial-guard.html" class="link-btn">🏦 Finance</a>
<a href="ceo-dashboard.html" class="link-btn">👔 CEO</a>
</div>
</div>`;
// INFRASTRUCTURE
const infra = `
<div class="card cy">
<div class="card-title"><span class="ico">🏗️</span>INFRASTRUCTURE</div>
<div class="row">
<div class="mini"><div class="mini-val">${v.infra.o365_tenants}</div><div class="mini-lbl">O365</div></div>
<div class="mini"><div class="mini-val">${v.infra.cf_accounts}</div><div class="mini-lbl">CF Accts</div></div>
<div class="mini"><div class="mini-val">${v.infra.cf_zones}</div><div class="mini-lbl">CF Zones</div></div>
<div class="mini"><div class="mini-val">${v.infra.domains}</div><div class="mini-lbl">Domains</div></div>
<div class="mini"><div class="mini-val">${v.infra.ia_accounts}</div><div class="mini-lbl">IA Accts</div></div>
<div class="mini"><div class="mini-val">${v.infra.personas}</div><div class="mini-lbl">Personas</div></div>
</div>
<div class="link-row">
<a href="cloudflare-manager.html" class="link-btn">☁️ CF</a>
<a href="office-admins.html" class="link-btn">📧 O365</a>
<a href="ia-provider-factory.html" class="link-btn">🤖 IA</a>
<a href="mail-personas.html" class="link-btn">🎭 Personas</a>
</div>
</div>`;
// CRM SEGMENTS
const segs = v.segments || [];
const hot = segs.find(s=>s.segment==='hot')?.cnt || 0;
const warm = segs.find(s=>s.segment==='warm')?.cnt || 0;
const cold = segs.find(s=>s.segment==='cold')?.cnt || 0;
const segments = `
<div class="card am">
<div class="card-title"><span class="ico">📇</span>CRM SEGMENTS</div>
<div class="row">
<div class="mini"><div class="mini-val" style="color:var(--rd)">${fmt(hot)}</div><div class="mini-lbl">🔥 Hot</div></div>
<div class="mini"><div class="mini-val" style="color:var(--am)">${fmt(warm)}</div><div class="mini-lbl">🌡️ Warm</div></div>
<div class="mini"><div class="mini-val" style="color:var(--d)">${fmt(cold)}</div><div class="mini-lbl">❄️ Cold</div></div>
</div>
<div class="bar"><div class="bar-fill rd" style="width:${v.data.crm_leads>0?hot/v.data.crm_leads*100:0}%"></div></div>
<div class="sub" style="margin-top:4px">Sync tracking → <a href="#" onclick="syncTracking()" style="color:var(--cy)">🔄 Sync Now</a></div>
<div class="link-row">
<a href="crm.php" class="link-btn">📇 Full CRM</a>
<a href="crm.php?filter=hot" class="link-btn">🔥 Hot</a>
<a href="crm.php?filter=clickers" class="link-btn">🖱️ Clickers</a>
</div>
</div>`;
dash.innerHTML = flowHTML + dataPools + ispHTML + capacity + brain + offers + tracking + revenue + infra + segments;
}
async function syncTracking() {
const r = await fetch(API+'?action=sync_tracking');
const d = await r.json();
alert(`Synced: ${d.opens_synced} opens, ${d.clicks_synced} clicks, ${d.conversions_synced} conversions`);
load();
}
load();
setInterval(load, 60000);
</script>
<?php include("/opt/wevads-arsenal/public/universal-drill.html"); ?>
</body>
</html>